fetch API 实现 GET 和 POST 请求

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 实现 GETPOST 请求的简单封装示例(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 实现 GETPOST 请求的简单封装示例(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
点赞 (0)
  1. ejsoon说道:
    Opera 65.2.3381.61420 Opera 65.2.3381.61420 Android 5.1.1 Android 5.1.1

    我以前在開發時,有時用XMLHttpRequest,有時也用fetch,感覺差不多。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code