原生 fetch 请求失败后(如无网络)状态会变成 reject 走 .catch 。绝大多数情况下业务场景只需要给个 toast 等简单处理。每个请求都 .catch 会显得格外繁琐,并且如果不 .catch, .then 里面的后续处理不会触发,可能会导致逻辑中断。

基于上述情况,可以封装公共请求方法处理异常情况,返回固定格式 { code, data, massage }, 只需在 .then 里面获取数据并处理。

目标

  1. 保留 fetch 语法不变
  2. 返回 promise,且状态一定变成 resolve,返回固定数据格式 { code, data, message }
  3. 给 url 动态添加域名
  4. 默认失败弹出 toast,且提供开关
  5. 默认请求中 loading,且提供开关

实现

实现如下

/**
* 返回 Promise({ code, data, message});
*/ import { message } from 'antd';
import { dispatch } from '../index';
import { startLoading, endLoading } from '../store/globalSlice'; // 在 config/env.js 中设置
export const origin = process.env.ORIGIN; interface MyInit extends RequestInit {
noToastError?: boolean; // 默认false
noLoading?: boolean; // 默认false
} // 请求返回统一格式
export class Response {
code: number;
data: any;
message: string | null;
constructor(code: number, data: any, message: string | null) {
this.code = code;
this.data = data;
this.message = message;
}
} export default (input: RequestInfo, myInit?: MyInit) => {
const init: MyInit = myInit || {}; // url 动态添加 origin
if (typeof input === 'string') {
if (!/https?:\/\//.test(input)) {
input = origin + input;
}
} // 开始 loading
if (!init?.noLoading) {
dispatch(startLoading());
} // 请求
return fetch(input, {
headers: {
'Content-Type': 'application/json',
},
...init,
})
.then((resp) => {
// code 不为 2xx
if (!/^2\d{2}$/.test(String(resp.status))) {
return new Response(resp.status, null, null);
} return resp
.json()
.then((json) => {
// toast错误信息
if (json.code !== 0) {
message.error(json.message);
} // 退出登陆
if (json.code === 20001) {
// logout();
// window.location.pathname = '/login';
} // 请求成功的数据
return json;
})
.catch((err) => {
// 不是 json 格式
return new Response(999998, null, 'data is not json.');
});
})
.catch((err) => {
// 请求发送失败
message.error('您的网络可能不通,请确认后重试');
return new Response(999999, null, err);
})
.finally(() => {
// 结束 loading
if (!init?.noLoading) {
dispatch(endLoading());
}
});
};

目前只完成了对 json 数据的处理。

其中 loading 部分用了 redux 和 @reduxjs/toolkit,用一个变量记录当前请求个数,控制实际 loading 开始和结束,实现如下:

let count = 0;
export const startLoading = () => (dispatch: any) => {
if (count === 0) {
dispatch(setLoding(true));
}
count++;
};
export const endLoading = () => (dispatch: any) => {
count--;
if (count === 0) {
dispatch(setLoding(false));
}
};

使用

import myfetch from './myfetch.ts';

myfetch('/xxx/xxx')
.then(res => console.log(res)) myfetch('https://www.xxx.com/xxx/xxx')
.then(res => console.log(res)) myfetch('/xxx/xxx', {
methods: 'POST',
body: JSON.stringify({}),
})
.then(res => console.log(res)) myfetch('/xxx/xxx', {
methods: 'POST',
body: JSON.stringify({}),
noToastError: true,
noLoading: true,
})
.then(res => console.log(res))

whosmeya.com

最新文章

  1. 如何在xml文件中加注释或取消注释
  2. android avoiding-memory-leaks
  3. 矩阵快速幂 POJ 3070 Fibonacci
  4. Bluebird-Core API(二)
  5. tty & pty & pts
  6. 百篇大计敬本年之系统篇《六》—— Ubuntu 16.04开启 root 超级用户
  7. Sharepoint中有关文件夹的操作
  8. MAC OS X 终端命令入门 (简单常用整理)
  9. greenlet代码解读
  10. C#实现文件批量重命名源码下载
  11. ESL翻译:Linear Methods for Regression
  12. TortoiseHg 学习笔记
  13. Qt 从菜单栏打开文件
  14. 8个爽滑如丝的Windows小软件,不好用你拿王思葱砸死我
  15. vs 附加进程 iis进程显示
  16. mysql不存在插入否则更新
  17. [NOI2018]你的名字(68pts)
  18. aop的概述
  19. python:ord()和chr()——字符串和ASCll编码转换
  20. jsp——js事件修改属性样式的两种方法(直接赋值、修改属性)、验证表单符合某要求、阻止表单提交、告诉浏览器不要缓存

热门文章

  1. 从0开始探究vue-组件化-组件之间传值
  2. Java实现 LeetCode 786 第 K 个最小的素数分数(大小堆)
  3. Java实现 蓝桥杯 算法训练 矩阵乘法
  4. Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
  5. [computer graphics]简单光照模型(Phong和Blinn-Phong)和明暗处理
  6. 在Asp.NET Core中如何优雅的管理用户机密数据
  7. Javascript 随机显示数组元素
  8. 【PHP】如何将SESSION数据存放到Redis中
  9. css3中的@font-face你真的了解吗
  10. c常用函数-sprintf