封装一个可扩展的Fectch开箱即用哦!!

306 阅读2分钟

不了解fetch的可先去看官方文档

话不多说直接上代码

export default class HTTP {

    /**
     * 拼接url参数
     * @returns {String}
     */
    static paramsToUrl(url, data) {
        let esc = encodeURIComponent;
        let queryParams = Object.keys(data)
            .map(k => `${esc(k)}=${esc(data[k])}`)
            .join('&');
        if (queryParams) url += `?${queryParams}`;
        return url;
    }

    /**
     * 设置返回默认请求头
     * @returns {Object}
     */
    static getHeaders() {
        return {
            headers: {}
        };
    }
    /**
     * 默认超时时间
     */
    static timeout = 60 *1000;

    static showLoading() {
    //根据实际情况写相应的loading图
    }

    static hideLoading() {
   
    }

    /**
     * 统一处理后台返回的结果, 包括业务逻辑报错的结果
     * @param result
     */
    static handleResult(result, cusOperation) {
        return result;
    }

    /**
     * 统一处fetch的异常, 不包括业务逻辑报错
     * @param result
     * ps: 通过 this.isHandleError 来判断是否需要有fetch方法来统一处理错误信息
     */
    static handleFailedResult(result, cusOperation) {
        return 'errorMsg';
    }

    /**
     * 控制Fetch请求是否超时
     * @returns {Promise}
     */
    static fetchTimeout(cusOperation) {
        const {isShowLoading} = cusOperation;
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (!cusOperation.isFetched) {
                    // 还未收到响应,则开始超时逻辑,并标记fetch需要放弃
                    cusOperation.isAbort = true;
                    // console.error('ERR: 请求超时')
                    if (isShowLoading) {
                        HTTP.hideLoading()
                    }
                    reject({fetchStatus: "timeout"})
                }
            }, cusOperation.timeout || HTTP.timeout);
        });
    }

    /**
     * 发送fetch请求
     * @param fetchUrl
     * @param fetchParams
     * @param cusOperation 使用者传递过来的参数, 用于以后的扩展自定义的行为
     * @returns {Promise}
     */
    static cusFetch(fetchUrl, fetchParams, cusOperation) {
        const {isShowLoading} = cusOperation;
        if (isShowLoading) {
            HTTP.showLoading();
        }
        cusOperation.isFetched = false;
        cusOperation.isAbort = false;
        // 处理自定义的请求头
        if (cusOperation.hasOwnProperty("cusHeader")) {
            const {cusHeader} = cusOperation;
            fetchParams.headers = Object.assign({}, fetchParams.headers, cusHeader)
        }
        // 2. 对fetch请求再进行一次Promise的封装
        const fetchPromise = new Promise((resolve, reject) => {
            fetch(fetchUrl, fetchParams).then(
                response => {
                    // 3. 放弃迟到的响应
                    if (cusOperation.isAbort) {
                        // 3. 请求超时后,放弃迟到的响应
                        return
                    }
                    if (isShowLoading) {
                        HTTP.hideLoading();
                    }
                    cusOperation.isFetched = true;
                    response.json().then(jsonBody => {
                        if (response.ok) {
                            // 4. 统一处理返回结果
                            resolve(jsonBody); //可根据后台数据 调用handleResult()做统一处理 而不是直接返回jsonBody
                        } else {

                            //可根据后端返回的错误信息格式做统一处理
                            reject(HTTP.handleFailedResult({
                                fetchStatus: "error",
                                netStatus: response.status,
                                error: 'msg'
                            }, cusOperation));
                        }
                    }).catch(e => {
                        const errMsg = e.name + " " + e.message;
                        reject(HTTP.handleFailedResult({
                            fetchStatus: "error",
                            error: errMsg,
                            netStatus: response.status
                        }, cusOperation));
                    });
                }
            ).catch(e => {
                const errMsg = e.name + " " + e.message;
                // console.error('ERR:', fetchUrl, errMsg)
                if (cusOperation.isAbort) {
                    // 请求超时后,放弃迟到的响应
                    return
                }
                if (isShowLoading) {
                    HTTP.hideLoading()
                }
                cusOperation.isFetched = true;
                // cusOperation.isHandleResult && Toast.info("网络开小差了,稍后再试吧", 2);
                reject(HTTP.handleFailedResult({fetchStatus: "error", error: errMsg}, cusOperation));
            });
        });
        return Promise.race([fetchPromise, HTTP.fetchTimeout(cusOperation)]);
    }

    /**
     * get 请求
     * @param url
     * @param params
     * @param cusOperation 使用者传递过来的参数, 用于以后的扩展自定义的行为
     * {
   *    isHandleResult: boolen    //是否需要处理错误结果   true 需要/false 不需要
   *    isShowLoading: boolen     //是否需要显示loading动画
   *    customHead: object        // 自定义的请求头
   *    timeout: int              //自定义接口超时的时间
   * }
     * @returns {Promise}
     */
    get(url, params = {}, cusOperation = {isHandleResult: true, isShowLoading: true}) {
        if (!cusOperation.hasOwnProperty("isHandleResult")) {
            cusOperation.isHandleResult = true
        }
        if (!cusOperation.hasOwnProperty("isShowLoading")) {
            cusOperation.isShowLoading = true
        }
        const method = "GET";
        const fetchUrl = HTTP.paramsToUrl(url, params); // 将参数转化到url上
        const fetchParams = Object.assign({}, {method}, HTTP.getHeaders());
        return HTTP.cusFetch(fetchUrl, fetchParams, cusOperation);
    }

    /**
     * post 请求
     * @param url
     * @param params
     * @param cusOperation 使用者传递过来的参数, 用于以后的扩展用户自定义的行为
     * @returns {Promise}
     */
    post(url, params = {}, cusOperation = {isHandleResult: true, isShowLoading: true}) {
        if (!cusOperation.hasOwnProperty("isHandleResult")) {
            cusOperation.isHandleResult = true
        }
        if (!cusOperation.hasOwnProperty("isShowLoading")) {
            cusOperation.isShowLoading = true
        }
        const method = "POST";
        const body = JSON.stringify(params); // 将参数转化成JSON字符串
        const fetchParams = Object.assign({}, {method, body}, HTTP.getHeaders());
        return HTTP.cusFetch(url, fetchParams, cusOperation);
    }

}

使用示例代码:

const http = new HTTP();
http.get('https://xxx.com/get',{data:'test'}).then((res) => {
        console.log(res);
    });
http.post('https://xxx.com/post',{data:'test'}).then((res) => {
        console.log(res);
    });

大功告成