解耦老项目的fetch模块

背景

接手公司的一个浙里办的项目, 由于接口请求实在太乱 , 遂找个时间简化一下 且项目代码还是复用以前的项目,还有很多冗余无用的代码, 如果有读者读到, 可以交流一下解构的思路

源代码如下:

jsx 复制代码
let requestNum = 0;
// 请求地址为一下数组项时,请求不带请求头
const ignoreHeader = //省略
function beginLoading(noLoading) {
  if (noLoading) return;

  if (requestNum === 0) {
    uni.showLoading({
      title: "加载中",
    });
  }

  requestNum++;
}

function endLoading(noLoading) {
  if (noLoading) return;
  requestNum--;

  if (requestNum <= 0) {
    requestNum = 0;
    uni.hideLoading();
  }
}

function getAppId() {
    //省略
  return appId;
}

function fetch(url, type = "get", data = {}, dataType, noLoading = false) {
  beginLoading(noLoading);
  return new Promise((resolve, reject) => {
    (url && url.startsWith("mgop.alibaba") )? handleMgop(url, type, data, dataType, noLoading, resolve, reject) : handleFetch(url, type, data, dataType, noLoading, resolve, reject);
  });
}

function uploadImg(url, filePath, formData = {}, noLoading = false) {
  //省略
}

function download(url, type = "get", data = {}, noLoading = false) {
  //省略
}
// 通用版upload,支持files或filePath方式上传
function commonUpload(config = { noLoading: false }) {
 //省略
}

function handleMgop(url, type, data, dataType, noLoading, resolve, reject) {
  //省略
  //这里原来错误的做法是把所有的数据处理, 包括针对错误的处理全都放在了这里
}

function handleFetch(url, type, data, dataType, noLoading, resolve, reject) {
  //省略
  //这里原来错误的做法是把所有的数据处理, 包括针对错误的处理全都放在了这里
}
export { uploadImg, fetch, download, commonUpload };

整体框架

不要把fetch放到api文件夹里面, 功能之间要有明显的区分

这里我放在了utils文件夹里面, 新建了一个fetch文件夹, 共有下面几个文件

index.js : 入口文件

handleReqLoading.js: 全局loading工具函数

errCode.js: 后端错误代码对应的json(值和value)

requestHandler.js : 请求处理器

responsehandler.js : 响应处理器

思路

第一步:

index.js导出 myFetch函数 , 这个作为请求函数, 应该只包含 :

  • 请求配置
  • 获取请求信息
  • 处理请求信息
  • 返回promise结果
  • 处理http错误

故代码如下:

jsx 复制代码
/**
 * 封装请求
 * @param url 请求地址
 * @param type 请求方式
 * @param data 请求参数
 * @param dataType 请求数据类型
 */
export const myFetch = async (url, type = "get", data = {}, dataType) => {
    const reqConfig = {
        url: httpApi + url,
        method: type,
        data: data,
        dataType: dataType,
        timeout: 60000,
        header: {
            'content-type': 'application/json',
            Token: '1'
        },
    }

    try {
        handleReqLoading(true);
        const response = await handleRequest(reqConfig);
        const responseData = handleNormalResponse(response);
        handleReqLoading(false);
        //返回一个promise对象
        return responseData;
    }catch (err) {
        return handleHttpError(err);
    }
}

这里把 处理错误信息, 处理请求, 处理相应 单独拿了出来, 方便以后扩展修改

处理请求(requestHandler.js)

这里把具体使用 uni.request.js的处理逻辑单独封装了起来, 它的职责就是, 接收请求配置, 发起请求, 返回 正确或错误的相应信息,

这里返回一个promise的原因是等待 接口请求, 父函数 await , 这样response 就是接口的响应值了

jsx 复制代码
export const handleRequest = async (reqConfig) => {
    return new Promise((resolve, reject) => {
        uni.request({
            ...reqConfig,
            success: function (res) {
                resolve(res);
            },
            fail: function (err) {
                reject(err);
            },
        });
    });
}

处理响应(responseHandler.js)

分为: 处理状态码为200 和不为200的响应

handleHttpError

这里使用errcode.js中的json来找出提示信息, 进行提示

jsx 复制代码
/**
 * 处理状态码不为200的响应
 */
export function handleHttpError(err) {
    const msg = errCodeMsgKV[err.code] + ':' + err.msg || err.msg;
    uni.showToast({
        title: msg,
        icon: "none",
        duration: 2000,
    });
    return Promise.reject(msg);
}

/**  errCode.js */
export const ErrCode = {
    /* 成功 */
    SUCCESS : 0,
    /* 系统内部错误 */
    SYSTEM_ERROR : 500,
    /* 不存在该资源 */
    NOT_FOUND : 404,
}

export const errCodeMsgKV = {
    [ErrCode.SUCCESS]: '成功',
    [ErrCode.SYSTEM_ERROR]: '系统内部错误',
    [ErrCode.NOT_FOUND]: '不存在该资源',
}

除了状态码的处理, 后端实际上应该要根据不同的业务返回不同的code, 然后前端定义一个businessErrcodeKV的json来对应提示, 后端目前不太规范, 会有返回状态码为200的 ,目前后端会有状态码为200, code为0, msg是提示错误信息的情况存在

handleNormalResponse

处理状态码为200的情况

除了状态码的处理, 后端实际上应该要根据不同的业务返回不同的code, 然后前端定义一个businessErrcodeKV的json来对应提示, 后端目前不太规范, 会有返回状态码为200的 ,目前后端会有状态码为200, code为0, msg是提示错误信息的情况存在

返回一个promise, 以便调用myfetch可以使用 .then

这个函数就可以根据不同的状态码来进行不同的逻辑操作了, 错误的统一处理在归纳在了myfetch文件夹里面, 这样 接口请求的时候更加简洁

jsx 复制代码
/**
 * 处理http响应码为200的响应
 * @return {Promise<unknown>}
 */
export function handleNormalResponse(res) {
    return new Promise((resolve, reject) => {
        if (res.statusCode || res.statusCode === 0) {
            switch (res.statusCode) {
                case 200:
                    resolve(res.data);
                    break;
                case 0:
                    resolve(res.data);
                    break;
                default:
                    reject(res.data);
                    uni.showToast({
                        title:res.data.msg,
                        icon: "none",
                        duration: 2000,
                    });
            }
        } else {
            reject(res.data);
            uni.showToast({
                title: "服务异常",
                icon: "none",
                duration: 2000,
            });
        }
    });
}
相关推荐
neter.asia14 分钟前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫15 分钟前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
光影少年34 分钟前
vue2与vue3的全局通信插件,如何实现自定义的插件
前端·javascript·vue.js
As977_35 分钟前
前端学习Day12 CSS盒子的定位(相对定位篇“附练习”)
前端·css·学习
susu108301891137 分钟前
vue3 css的样式如果background没有,如何覆盖有background的样式
前端·css
Ocean☾39 分钟前
前端基础-html-注册界面
前端·算法·html
Dragon Wu41 分钟前
前端 Canvas 绘画 总结
前端
CodeToGym1 小时前
Webpack性能优化指南:从构建到部署的全方位策略
前端·webpack·性能优化
~甲壳虫1 小时前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫1 小时前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js