Fetch API 是 XMLHttpRequest 实现功能的一个更理想的替代方案,它提供了一个 JavaScript 接口,用于异步的执行 http 请求。
在常规的简单接口调试中,使用 Fetch API 可以在浏览器控制台快速的发起一个接口请求,并查看其返回结果。下面是相关实现的示例(备份:用于快速查找使用)。
Fetch API 执行 Get
请求示例:
await fetch(url, { method: 'GET', credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, }).then(response => response.json());
Fetch API 执行 POST
请求示例:
await fetch(url, { method: 'POST', credentials: 'include', body: JSON.stringify(params), headers: { Accept: 'application/json', 'Content-Type': 'application/json', }, }).then(response => response.json());
基于 Fetch API 实现 GET
和 POST
请求的简单封装示例(TypeScript):
type PlainObject = Record<string, any>; export interface APIResponse< T = PlainObject> extends PlainObject { data: T; errorNo: number; errorInfo?: string; success?: boolean; } function toQueryString(params?: Record<string, unknown>) { if (!params) return ''; return Object.entries(params) .map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))}`) .join('&'); } function toFormData(params: Record<string, unknown>) { const form = new FormData(); Object.entries(params).forEach(([key, val]) => { form.append(key, typeof val !== 'string' && !(val instanceof Blob) ? JSON.stringify(val) : val); }); return form; } async function handlerResponse< T>(response: Response) { const result: APIResponse< T> = { errorNo: 0, data: [] as never }; try { const res: APIResponse< T> = await response.json(); Object.assign(result, res); result.errorNo = +result.errorNo || 0; } catch (err) { const reason = err as { message?: string }; (window.logger || console).error(`[http][get][err]`, reason.message || reason); if (response.status !== 200) result.errorNo = response.status || -400; result.errorInfo = response.statusText || reason.message; } // logger.debug(`[http][req][response]`, result.errorNo, result); return result; } export const httpRequest = { baseHref: '', get< T = PlainObject>(url: string, params?: PlainObject, headers?: RequestInit['headers']): Promise<APIResponse< T>> { const qs = toQueryString(params); if (qs) url += url.includes('?') ? `&${qs}` : `?${qs}`; if (this.baseHref && !url.startsWith(this.baseHref)) { url = this.baseHref + url; } return fetch(url, { method: 'GET', credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...headers, }, }).then(response => handlerResponse< T>(response)); }, post< T = PlainObject>( url: string, params: PlainObject, headers?: RequestInit['headers'], type: 'json' | 'formdata' | 'payload' = 'json' ): Promise<APIResponse< T>> { if (this.baseHref && !url.startsWith(this.baseHref)) { url = this.baseHref + url; } return fetch(url, { method: 'POST', credentials: 'include', body: type === 'formdata' ? toFormData(params) : type === 'payload' ? toQueryString(params) : JSON.stringify(params), headers: { Accept: 'application/json', 'Content-Type': type === 'json' ? 'application/json;charset=UTF-8' : 'application/x-www-form-urlencoded;charset=UTF-8', ...headers, }, }).then(response => handlerResponse< T>(response)); }, };
基于 Fetch API 实现 GET
和 POST
请求的简单封装示例(JavaScript):
function toQueryString(params) { if (!params) return ''; return Object.entries(params) .map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(typeof val === 'string' ? val : JSON.stringify(val))}`) .join('&'); } function toFormData(params) { const form = new FormData(); Object.entries(params).forEach(([key, val]) => { form.append(key, typeof val !== 'string' && !(val instanceof Blob) ? JSON.stringify(val) : val); }); return form; } async function handlerResponse(response) { const result = { errorNo: 0, data: [] }; try { const res = await response.json(); Object.assign(result, res); result.errorNo = +result.errorNo || 0; } catch (err) { const reason = err; (window.logger || console).error(`[http][get][err]`, reason.message || reason); if (response.status !== 200) result.errorNo = response.status || -400; result.errorInfo = response.statusText || reason.message; } // logger.debug(`[http][req][response]`, result.errorNo, result); return result; } const httpRequest = { baseHref: '', get(url, params, headers) { const qs = toQueryString(params); if (qs) url += url.includes('?') ? `&${qs}` : `?${qs}`; if (this.baseHref && !url.startsWith(this.baseHref)) { url = this.baseHref + url; } return fetch(url, { method: 'GET', credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', ...headers, }, }).then(response => handlerResponse(response)); }, post( url, params, headers, type ) { if (this.baseHref && !url.startsWith(this.baseHref)) { url = this.baseHref + url; } return fetch(url, { method: 'POST', credentials: 'include', body: type === 'formdata' ? toFormData(params) : type === 'payload' ? toQueryString(params) : JSON.stringify(params), headers: { Accept: 'application/json', 'Content-Type': type === 'json' ? 'application/json;charset=UTF-8' : 'application/x-www-form-urlencoded;charset=UTF-8', ...headers, }, }).then(response => handlerResponse(response)); }, };
- https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
我以前在開發時,有時用XMLHttpRequest,有時也用fetch,感覺差不多。