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.互斥的概念 互斥指的是任何时刻,互斥保证有且只有一个执行流进入临界区,进行临界资源的访问,通…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...