解耦老项目的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,
            });
        }
    });
}
相关推荐
火星思想4 分钟前
都2025年了,还在问构建工具是干嘛的?
前端·前端框架·设计
杨进军7 分钟前
MutationObserver 实现 iframe 自适应高度
前端
火星思想8 分钟前
Promise 核心知识点(非基础)
前端·javascript·面试
前端大白话9 分钟前
炸裂!10个 React 实战技巧,让你的代码从“青铜”秒变“王者”
前端·javascript·react.js
Paramita10 分钟前
Koa源码解读
前端
用户614722537720310 分钟前
JavaScript 性能优化实战:从理论到落地的全面指南
前端
专业掘金10 分钟前
0426 手打基础丸
前端
WEI_Gaot15 分钟前
React 19 Props 和 react-icons 和 事件处理函数
前端·react.js
10年前端老司机15 分钟前
微信小程序模板语法和事件
前端·javascript·微信小程序
龙在天16 分钟前
Promise.withResolvers() vs 传统 Promise:谁更胜一筹?
前端