原生 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

基于 fetch 的请求封装的更多相关文章

  1. 简单的基于Vue-axios请求封装

    具体实现思路=>封装之前需要用npm安装并引入axios,使用一个单独的js模块作为接口请输出对象,然后export dafult 这个对象. 1.首先我们需要在Vue实例的原型prototyp ...

  2. React Native 网络请求封装:使用Promise封装fetch请求

    最近公司使用React作为前端框架,使用了异步请求访问,这里做下总结: React Native中虽然也内置了XMLHttpRequest 网络请求API(也就是俗称的ajax),但XMLHttpRe ...

  3. react-native fetch 请求封装

    1.fetch 函数封装 fetch.js /** * 请求头 * @type {{Accept: string, Content-Type: string}} */ const header = { ...

  4. uniapp 基于 flyio 的 http 请求封装

    之前写请求都是用别人封装好的,直接 import request 完事,自己第一次写还是一头雾水,学习了一波搞清楚了些,可以写简单的封装了. 首先要搞清楚为什么封装请求,同其他的封装一样,我们把不同请 ...

  5. 基于小程序请求接口 wx.request 封装的类 axios 请求

    基于小程序请求接口 wx.request 封装的类 axios 请求 Introduction wx.request 的配置.axios 的调用方式 源码戳我 feature 支持 wx.reques ...

  6. WebApi系列~基于单请求封装多请求的设计

    回到目录 怎么说,单请求封装多请求,这句话确实有点绕了,但还是要看清楚,想明白这到底是怎么一回事,单请求即一次请求(get,post,put,delete),封闭多请求,即在客户端发送的一个请求中可能 ...

  7. iOS开发之网络请求(基于AFNetworking的再封装)

    最近一直很忙也没有什么时间写博客了.放假了休息一下,就写一篇博客来总结一下最近做项目中出现过的问题吧!!! 首先,在项目中我的起到了什么作用,无非就是把美工(UI设计师)给我们的图显示出来,然后再和服 ...

  8. webapi基于单请求封装多请求的设计【转】

    怎么说,单请求封装多请求,这句话确实有点绕了,但还是要看清楚,想明白这到底是怎么一回事,单请求即一次请求(get,post,put,delete),封闭多请求,即在客户端发送的一个请求中可能包含多个子 ...

  9. fetch 如何请求数据

    fetch 如何请求数据 在 传统Ajax 时代,进行 API 等网络请求都是通过XMLHttpRequest或者封装后的框架进行网络请求,然而配置和调用方式非常混乱,对于刚入门的新手并不友好 二 与 ...

随机推荐

  1. git可视化打包更新文件

    每次当我们修改了项目代码的时候,总需要理出来一个更新包发给测试部门或者给客户更新.当我们一次的修改的代码多了之后,我们就很难按照文件夹一个一个的去提交出来哪些的更新的,哪些是未修改的.于是乎就在度娘能 ...

  2. Java实现 LeetCode 823 带因子的二叉树(DP)

    823. 带因子的二叉树 给出一个含有不重复整数元素的数组,每个整数均大于 1. 我们用这些整数来构建二叉树,每个整数可以使用任意次数. 其中:每个非叶结点的值应等于它的两个子结点的值的乘积. 满足条 ...

  3. Java实现 LeetCode 606 根据二叉树创建字符串(遍历树)

    606. 根据二叉树创建字符串 你需要采用前序遍历的方式,将一个二叉树转换成一个由括号和整数组成的字符串. 空节点则用一对空括号 "()" 表示.而且你需要省略所有不影响字符串与原 ...

  4. Java实现 LeetCode 590 N叉树的后序遍历(遍历树,迭代法)

    590. N叉树的后序遍历 给定一个 N 叉树,返回其节点值的后序遍历. 例如,给定一个 3叉树 : 返回其后序遍历: [5,6,3,2,4,1]. 说明: 递归法很简单,你可以使用迭代法完成此题吗? ...

  5. 第三届蓝桥杯JavaC组国(决)赛真题

    解题代码部分来自网友,如果有不对的地方,欢迎各位大佬评论 题目1. 填算式 [结果填空] (满分11分) 看这个算式: ☆☆☆ + ☆☆☆ = ☆☆☆ 如果每个五角星代表 1 ~ 9 的不同的数字. ...

  6. Java实现 蓝桥杯 算法提高 双十一抢购

    试题 算法提高 双十一抢购 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 一年一度的双十一又来了,某网购网站又开始了半价销售的活动. 小G打算在今年的双十一里尽情地购物,以享受购买 ...

  7. java实现奇怪的比赛

    ** 奇怪的比赛** 某电视台举办了低碳生活大奖赛.题目的计分规则相当奇怪: 每位选手需要回答10个问题(其编号为1到10),越后面越有难度.答对的,当前分数翻倍:答错了则扣掉与题号相同的分数(选手必 ...

  8. PAT 挖掘机技术哪家强

    为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即参赛人数.随后 N  ...

  9. Liunx常用运维命令整理记录

    前言 作为后端开发者,掌握一些常用的运维命令也是很有必要的,本文记录常用Liunx运维命令 基本命令 目录切换 cd base-admin/ 切换到当前目录下的base-admin目录 cd .. 切 ...

  10. 纯正中文版本pi-star系统下载

    基于3.4.17修改(稳定,发热量少) 不支持RPI 4 a/b+ 完美支持树莓派0,1,2,3 默认刷好卡,启动已经设置好所有参数(选好TFT屏幕,调制解调器类型GPIO,打开了DMR服务器(460 ...