fetch学习笔记——封装

文章参考

  1. 用fetch与服务器进行交互时headers中content-type的配置问题以及涉及到的跨域问题
  2. 使用fetch上传文件失败的解决方案

问题描述

学习使用react,与后台交互使用的是fetch作为API请求,因此,之前一直都是使用的ajax,需要引入jquery库,如果使用fetch则默认浏览(比较高版本的chrome,早期的IE不支持)自带。

知识点

  1. 与后台交互数据,发送的JSON对象,要全部序列化,转为get请求的字符串
  2. 如果是上传文件,则不能添加Header配置,否则后台无法获取数据
  3. fetch是下一代API的标准,是替代ajax的解决方案,因此目前很多浏览器已经兼容

自己封装的API 案例

/**
 *  基于fetch 在浏览器中发送请求库的封装
 */
// export const
    HTTPUtil = {
    // 弹出"菊花"效果
    showLoading: function () {
        // Toast.loading("请求中", 5000, function () {
        //     console.log('close');
        // }, true);
    },
    // 关闭 "菊花" 效果
    hideLoading: function () {
        // Toast.hide();
    },
    // 在header中添加token
    setTokenInHeader: function () {

    },
    // json 转为 get请求的字符串
    json_to_get: function (jsonObj) {
        return Object.keys(jsonObj).map(function (key) {
            // body...
            return encodeURIComponent(key) + "=" + encodeURIComponent(jsonObj[key]);
        }).join("&");
    },
    // get 请求字符串转为json
    get_to_json: function (sstr) {
        sstr = sstr.replace(/&/g, '","').replace(/=/g, '":"');
        sstr = '{"' + sstr + '"}';
    },
    fetchAction: function (url, fetchConfig) {
        var that = this;
        return new Promise(function (resolve, reject) {
            fetch(url, fetchConfig)
            // then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
            // 第一个then的response返回的是 服务器响应的信息 —— 包括 header content-type body 等信息
            // 只要不是后台报错,响应都是成功的,比如 404 ,403, 500等是成功返回
            .then(function (response) {
                // 如果是成功返回
                if (response.ok) {
                    // 这个函数返回的是接口响应的值,执行后面的then 方法
                    return response.json();
                } else {
                    // 后台报错,执行后面的catch方法
                    reject({
                        status: response.status
                    })
                }
            })
            .then(function (response) {
                resolve(response);
            })
            .catch (function (err) {
                reject({
                    status: -1
                });
            })
            // 无论成功和失败,都需要执行该方法,用来关闭菊花效果
            .finally(function () {
                that.hideLoading();
            })
        });
    },

    /**
     * 基于 fetch 封装的 GET请求
     * @param url
     * @param params {}
     * @param headers
     * @returns {Promise}
     */
    get: function (url, params, headers) {
        var that = this;
        this.showLoading();
        var headerObj = {};
        if (params) {
            var paramsArray = [];
            //encodeURIComponent
            Object.keys(params).forEach(function (key) {
                paramsArray.push(key + '=' + params[key])
            });
            if (url.search(/\?/) === -1) {
                url += '?' + paramsArray.join('&')
            } else {
                url += '&' + paramsArray.join('&')
            }
        }
        // 判断用户是否添加了值
        if (headers === undefined) {
            headerObj = {};
        } else {
            headerObj = headers;
        }
        // 设置token在header中
        this.setTokenInHeader(headerObj);

        var fetchConfig = {
            method: 'GET',
            headers: headerObj,
        }
        return that.fetchAction(url, fetchConfig);
    },
    /**
     * 基于 fetch 封装的 POST请求  FormData 表单数据
     * @param url
     * @param formData
     * @param headers
     * @returns {Promise}
     */
    post: function (url, params, headers) {
        var that = this;
        this.showLoading();
        var formDataObj = null; // 传递的参数
        var headerObj = {}; // 设置请求头对象
        if (params === undefined) {
            formDataObj = "";
        } else {
            // 判断传递过来的是否是对象,如果是JSON 对象,需要序列化JSON数据,后台才能接受的刀
            if (params instanceof Object) {
                formDataObj = that.json_to_get(params)
            } else { // 如果不是JSON,则直接使用用户传递过来的值
                formDataObj = params;
            }
        }
        // 判断用户是否添加了值
        if (headers === undefined) {
            headerObj['Content-type'] = 'application/x-www-form-urlencoded';
        } else {
            headerObj = headers;
        }
        // 设置token在header中
        this.setTokenInHeader(headerObj);
        var fetchConfig = {
            method: 'POST',
            mode: 'cors',
            headers: headerObj,
            body: formDataObj,
        };
        return that.fetchAction(url, fetchConfig);
    },
    postUpload: function (url, formdata, headers) {
        var that = this;
        this.showLoading();
        var uploadReq = new Request('http://localhost:3000/fetch/upload', { //url为服务器接口URL
            method: "POST",
            body: formdata
        });
        return new Promise(function (resolve, reject) {
            fetch(uploadReq)
            // then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
            // 第一个then的response返回的是 服务器响应的信息 —— 包括 header content-type body 等信息
            // 只要不是后台报错,响应都是成功的,比如 404 ,403等是成功返回
                .then(function (response) {
                    // 如果是成功返回
                    if (response.ok) {
                        // response.json读取服务器发来的JSON数据,response.json返回Promise,所以可以链式调用.then方法
                        return response.json();
                    } else {
                        // 后台报错,执行后面的catch方法
                        reject({
                            status: response.status
                        })
                    }
                })
                .then(function (response) {
                    resolve(response);
                })
                .catch (function (err) {
                    reject({
                        status: -1
                    });
                })
                // 无论成功和失败,都需要执行该方法,用来关闭菊花效果
                .finally(function () {
                    that.hideLoading();
                })
        });
    }
};

没有更多推荐了,返回首页

私密
私密原因:
请选择设置私密原因
  • 广告
  • 抄袭
  • 版权
  • 政治
  • 色情
  • 无意义
  • 其他
其他原因:
120
出错啦
系统繁忙,请稍后再试