axios的替代方案onion-middleware
onion-middleware的由来
嗯。。。闲来无事瞎搞的!!!!主要用来实现请求/相应拦截,当然队列性的数据操作都是可以的
直接上使用教程
- 安装
npm install onion-middleware
- 使用
import { OnionMiddleware } from 'onion-middleware'// vite等模块化加载的工具需调用clearMiddleware
app.clearMiddleware()// 创建一个中间件应用
const app = new OnionMiddleware()// 添加中间件
app.use(async (ctx, next) => {// Middleware Before to do somethingnext()// Middleware After to do something
})
- 实战使用
import { BaseResponse, CtxType, FetchOptionsType } from './type';
import storage from '../storage';
import { sortObject } from '../common';
import { aesDecrypt, aesEncrypt } from './cryproUtil';
import config from '@/configs/config';
import { message } from 'antd';
import { OnionMiddleware } from 'onion-middleware'
const pendingPromises: { [key: string]: any } = {};
export const fetchApi = (options: FetchOptionsType) => {const { url, timeout, headers, method, data = {}, ...args } = options || {};const queryData =data instanceof FormData ? data : JSON.parse(JSON.stringify(data)); // 去掉undefined的属性值let conpleteUrl = url;const reqOptions = { ...args, headers, method };if (['GET', 'DELETE'].includes(method?.toUpperCase())) {conpleteUrl = url + '?';for (let key in queryData) {const val = queryData[key]conpleteUrl += `${key}=${typeof val === 'object' ? JSON.stringify(val) : encodeURIComponent(queryData[key])}&`;}} else {reqOptions.body =typeof queryData === 'string' || queryData instanceof FormData? queryData: JSON.stringify(queryData);if (queryData instanceof FormData) {delete reqOptions.headers['Content-Type'];}}return Promise.race([fetch(conpleteUrl, reqOptions).then((response) => {return response.json();}).catch((e) => {return JSON.stringify({code: 504,msg: '连接不到服务器',});}),new Promise((_, reject) =>setTimeout(() => reject(new Error('Request timeout')), timeout)),]);
};const app = new OnionMiddleware()
app.clearMiddleware();// 特殊业务处理中间件(401),以及相应数据的ts类型定义
app.use(async (ctx: CtxType, next: (arg?: any) => void) => {// Middleware Beforeawait next();// Middleware Afterconst { response } = ctx;// 401,1401 重新静默登录if ([401, 1401].includes(response?.code)) {// 未登录storage.clearAll();message.error('登录过期,请重新登陆!');// to do something}
});// 重复请求复用中间件
app.use(async (ctx: CtxType, next: (arg?: any) => void) => {// Middleware Beforeconst { request } = ctx;// 使用请求信息作为唯一的请求key,缓存正在请求的promise对象// 相同key的请求将复用promiseconst requestKey = JSON.stringify([request.method.toUpperCase(),sortObject(request.data),]);if (pendingPromises[requestKey]) {console.log('重复请求,已合并请求并返回共享的第一次请求,参数:', request);await next({shouldAbort: true,callback: () => {return pendingPromises[requestKey];},});} else {await next();}// Middleware Afterdelete pendingPromises[requestKey];
});// 请求/相应信息输出中间件
app.use(async (ctx: CtxType, next: (arg?: any) => void) => {// Middleware Beforeawait next();// Middleware Afterconst { request, response } = ctx;if (request?.errorTip && ![200, 401, 1401].includes(response.code)) {message.error(response.msg);}console.log('请求参数', {url: request?.url,data: request?.originData,method: request?.method,});console.log('响应参数', response);
});// header处理中间件(此中间件位于)
app.use(async (ctx: CtxType, next: (arg?: any) => void) => {// Middleware Beforeconst { request, response } = ctx;const token = storage.getItem('token');if (token) {// 请求头token信息,请根据实际情况进行修改request.headers['Authorization'] = 'Bearer ' + token;}ctx.request = request;await next();// Middleware After
});// 加解密
app.use(async (ctx: CtxType, next: (arg?: any) => void) => {// Middleware Beforeconst { request } = ctx;request.originData = request.data;if (config.OPEN_ENCRYPTION) {const aesData = aesEncrypt(request.data);// 加密request.data = { encryptedReqData: aesData[0] };// signrequest.headers['sign'] = aesData[1];}await next();// Middleware Afterif (config.OPEN_ENCRYPTION) {if (ctx.response?.encryptedResData) {ctx.response = aesDecrypt(ctx.response?.encryptedResData || '') || '{}';}}
});// 公共请求发送方法(简约)
const send = <T>(options: any): Promise<T> => {const { errorTip = true } = options;// HTTP请求上下文const ctx: CtxType = {request: {...options,errorTip,config: {timeout: 60 * 1000,baseUrl: config.VITE_API_URL + config.VITE_BASE_URL,},headers: {'Content-Type': 'application/json',},},promise: { resolve: () => { }, reject: () => { } },};const baseRequest = new Promise((resolve: (arg: T) => void, reject) => {// 打破promise回调作用域,在其他地方实现调用ctx.promise.resolve = resolve;ctx.promise.reject = reject;// 执行中间件app.execute(ctx, () => {let { config } = ctx?.request || {};const { data, method, url, headers } = ctx?.request || {};const fetchPromise = new Promise(async (_resolve) => {config = {...config,data,headers,url: config.baseUrl + (url || ''),method: method.toUpperCase(), // 配置method方法};const res = await fetchApi({...options,...config,});_resolve(res);});return fetchPromise;}).then(() => { }).catch((err) => {console.log(err);});});// 使用请求信息作为唯一的请求key,缓存正在请求的promise对象// 相同key的请求将复用promiseconst requestKey = JSON.stringify([options.method.toUpperCase(),options.url,sortObject(options.data),]);// 存储第一次请求引用 (重复请求判断需要)if (!pendingPromises[requestKey]) {pendingPromises[requestKey] = baseRequest;}return baseRequest;
};// 公共请求发送方法
const sendApi = <T = BaseResponse>(options: FetchOptionsType): Promise<T> => {return send(options);
};export default sendApi;
效果简单截个图吧,拿请求/相应信息输出中间件为例,效果如下:
结尾
轻点喷😂😂😂
相关文章:

axios的替代方案onion-middleware
onion-middleware的由来 嗯。。。闲来无事瞎搞的!!!!主要用来实现请求/相应拦截,当然队列性的数据操作都是可以的 直接上使用教程 安装 npm install onion-middleware使用 import { OnionMiddleware } from onion…...
设计模式——泛型单例类
游戏中很多管理类都需要写成单例类,每次重复把管理类设置为单例类很繁琐, 这里直接写一个泛型单例类作为模板父类,方便其他需要写成单例类的类直接继承设置为单例类; using UnityEngine;public class Singleton<T> : Mono…...

三维卷积( 3D CNN)
三维卷积( 3D CNN) 1.什么是三维卷积 1.1 三维卷积简介 二维卷积是在单通道的一帧图像上进行滑窗操作,输入是高度H宽度W的二维矩阵。 三维卷积输入多了深度C这个维度,输入是高度H宽度W深度C的三维矩阵。在卷积神经网络中&…...

【JAVA】Java开发小游戏 - 简单的2D平台跳跃游戏 基本的2D平台跳跃游戏框架,适合初学者学习和理解Java游戏开发的基础概念
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默, 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把…...

分享3个国内使用正版GPT的网站【亲测有效!2025最新】
1. molica 传送入口:https://ai-to.cn/url/?umolica 2. 多帮AI 传送入口:https://aigc.openaicloud.cn?inVitecodeMYAAGGKXVK 3. 厉害猫 传送入口:https://ai-to.cn/url/?ulihaimao...

CSDN Markdown编辑器设置视频居中完美解决方案
表格做中间容器,把视频放在表格里面,利用表格居中语法实现表格内元素居中对齐,从而完美实现视频居中。 【三角符文】jevil战无伤通关 这玩意整了我两个星期,焦头烂额都找不到解决方案。今天偶然想到可以用表格试试,没想…...

Java到底是值传递还是引用传递????
在搞懂这个问题之前, 我们要首先了解什么是值传递, 什么是引用传递? 值传递: 传递的是数据的副本,修改副本不会影响原始数据。引用传递: 传递的是数据的引用(地址),修改引用会直接影响原始数据. 也就是说,值传递和引…...

初学stm32 --- 电源监控
目录 STM32 电源监控介绍 上电/掉电复位POR/PDR(F1) 可编程电压检测器(PVD)(F1) PVD相关寄存器介绍(F1) 电源控制寄存器 PWR_CR 电源控制/状态寄存器 PWR_CSR PVD相关HAL库驱动介绍 PVD的使用步骤 …...

Win10本地部署大语言模型ChatGLM2-6B
鸣谢《ChatGLM2-6B|开源本地化语言模型》作者PhiltreX 作者显卡为英伟达4060 安装程序 打开CMD命令行,在D盘新建目录openai.wiki if not exist D:\openai.wiki mkdir D:\openai.wiki 强制切换工作路径为D盘的openai.wiki文件夹。 cd /d D:\openai.wik…...
[ LeetCode 75 ] 1768. 交替合并字符串
题目描述:(相关标签:双指针、字符串) 给你两个字符串 word1 和 word2 。请你从 word1 开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。 返…...
(三)通过WebGL绘制一个简单的三角形来理解渲染管线
理解 WebGL 绘图原理的关键是了解它的渲染管线。WebGL 渲染管线实际上是由多个阶段组成的,每个阶段都有特定的任务,最终输出的是屏幕上的图像。为了让你能轻松理解这些原理,我将通过一个简单的例子来详细解释。 绘制一个简单的三角形 我们将…...

医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件
3D Slicer 是一款功能全面的开源医学影像分析软件,广泛应用于影像处理、三维建模、影像配准和手术规划等领域。它支持多种医学影像格式(如 DICOM、NIfTI)和丰富的插件扩展,是神经科学、放射学和生物医学研究中不可或缺的工具。 在…...

Ollama VS LocalAI:本地大语言模型的深度对比与选择指南
随着人工智能技术的快速发展,大语言模型逐渐成为多个行业的重要工具。从生成内容到智能问答,大模型展现了强大的应用潜力。然而,云端模型的隐私性、使用成本和网络依赖等问题也促使更多用户关注本地化解决方案。Ollama 和 LocalAI 是近年来备…...

虚表 —— 隐藏行(简单版)
因为隐藏行改变了listview内部行号处理机制,需要处理大量细节,如listview内部用于传递行号的各种消息、通知等、封装的各种读取行号的函数等。 所以在工作量很大,一处纰漏可能导致重大bug的情况下,仅对隐藏行功能进行了简单封装&…...

CAD批量打印可检索的PDF文件
本文虽介绍CAD使用方法,但还是劝告大家尽早放弃使用CAD软件。。。。太TM难用了 当你打开CAD时发现如下一堆图纸,但是不想一个一个打印时。你可以按照下面操作实现自动识别图框实现批量打印。 1.安装批量打印插件 2.安装后打开CAD,输入命令Bp…...

2025.1.7(c++基础知识点)
作业(练习) 练习:要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩,分别完成空间的申请、成绩的录入、升序排序、成绩输出函数以及空间释放函数,并在主程序中完成测试 要求使用new和delete完成 #include &…...

jenkins入门12-- 权限管理
Jenkins的权限管理 由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,我们使用Role-based Authorization Strategy 插件 只有项目读权限 只有某个项目执行权限...

Edge SCDN高效防护与智能加速
当今数字化时代,网络安全和内容分发效率已成为企业业务发展的关键因素。酷盾安全推出了Edge SCDN解决方案,为企业提供全方位的安全防护和高效的内容分发服务。 一、卓越的安全防护能力 1.DDoS攻击的精准防御:Edge SCDN具备强大的DDoS攻击检测…...
Ubuntu22.04配置静态ip
1. 编辑网络配置文件 sudo vim /etc/netplan/00-installer-config.yaml 2.输入下面配置 将静态ip设置为192.168.3.200 ,并设置路由器地址192.168.3.1,以及dns地址 223.5.5.5和223.6.6.6 dhcp4: false 表示取消动态分配ip network:ethernets:e…...

[Linux]线程的互斥与同步
目录 一、互斥 1.互斥的概念 2.互斥锁接口 3.线程加锁解锁本质 4.死锁 二、同步 1.同步的概念 2.条件变量 3.条件变量接口 一、互斥 1.互斥的概念 互斥指的是任何时刻,互斥保证有且只有一个执行流进入临界区,进行临界资源的访问,通…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...

Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...

Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...