当前位置: 首页 > news >正文

axios的替代方案onion-middleware

onion-middleware的由来

嗯。。。闲来无事瞎搞的!!!!主要用来实现请求/相应拦截,当然队列性的数据操作都是可以的

直接上使用教程

  1. 安装
npm install onion-middleware
  1. 使用
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
})
  1. 实战使用
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的由来 嗯。。。闲来无事瞎搞的&#xff01;&#xff01;&#xff01;&#xff01;主要用来实现请求/相应拦截&#xff0c;当然队列性的数据操作都是可以的 直接上使用教程 安装 npm install onion-middleware使用 import { OnionMiddleware } from onion…...

设计模式——泛型单例类

游戏中很多管理类都需要写成单例类&#xff0c;每次重复把管理类设置为单例类很繁琐&#xff0c; 这里直接写一个泛型单例类作为模板父类&#xff0c;方便其他需要写成单例类的类直接继承设置为单例类&#xff1b; using UnityEngine;public class Singleton<T> : Mono…...

三维卷积( 3D CNN)

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

【JAVA】Java开发小游戏 - 简单的2D平台跳跃游戏 基本的2D平台跳跃游戏框架,适合初学者学习和理解Java游戏开发的基础概念

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c; 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把…...

分享3个国内使用正版GPT的网站【亲测有效!2025最新】

1. molica 传送入口&#xff1a;https://ai-to.cn/url/?umolica 2. 多帮AI 传送入口&#xff1a;https://aigc.openaicloud.cn?inVitecodeMYAAGGKXVK 3. 厉害猫 传送入口&#xff1a;https://ai-to.cn/url/?ulihaimao...

CSDN Markdown编辑器设置视频居中完美解决方案

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

Java到底是值传递还是引用传递????

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

初学stm32 --- 电源监控

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

Win10本地部署大语言模型ChatGLM2-6B

鸣谢《ChatGLM2-6B&#xff5c;开源本地化语言模型》作者PhiltreX 作者显卡为英伟达4060 安装程序 打开CMD命令行&#xff0c;在D盘新建目录openai.wiki if not exist D:\openai.wiki mkdir D:\openai.wiki 强制切换工作路径为D盘的openai.wiki文件夹。 cd /d D:\openai.wik…...

[ LeetCode 75 ] 1768. 交替合并字符串

题目描述&#xff1a;&#xff08;相关标签&#xff1a;双指针、字符串&#xff09; 给你两个字符串 word1 和 word2 。请你从 word1 开始&#xff0c;通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长&#xff0c;就将多出来的字母追加到合并后字符串的末尾。 返…...

(三)通过WebGL绘制一个简单的三角形来理解渲染管线

理解 WebGL 绘图原理的关键是了解它的渲染管线。WebGL 渲染管线实际上是由多个阶段组成的&#xff0c;每个阶段都有特定的任务&#xff0c;最终输出的是屏幕上的图像。为了让你能轻松理解这些原理&#xff0c;我将通过一个简单的例子来详细解释。 绘制一个简单的三角形 我们将…...

医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件

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

Ollama VS LocalAI:本地大语言模型的深度对比与选择指南

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

虚表 —— 隐藏行(简单版)

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

CAD批量打印可检索的PDF文件

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

2025.1.7(c++基础知识点)

作业&#xff08;练习&#xff09; 练习&#xff1a;要求在堆区连续申请5个int的大小空间用于存储5名学生的成绩&#xff0c;分别完成空间的申请、成绩的录入、升序排序、成绩输出函数以及空间释放函数&#xff0c;并在主程序中完成测试 要求使用new和delete完成 #include &…...

jenkins入门12-- 权限管理

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

Edge SCDN高效防护与智能加速

当今数字化时代&#xff0c;网络安全和内容分发效率已成为企业业务发展的关键因素。酷盾安全推出了Edge SCDN解决方案&#xff0c;为企业提供全方位的安全防护和高效的内容分发服务。 一、卓越的安全防护能力 1.DDoS攻击的精准防御&#xff1a;Edge SCDN具备强大的DDoS攻击检测…...

Ubuntu22.04配置静态ip

1. 编辑网络配置文件 sudo vim /etc/netplan/00-installer-config.yaml 2.输入下面配置 将静态ip设置为192.168.3.200 &#xff0c;并设置路由器地址192.168.3.1&#xff0c;以及dns地址 223.5.5.5和223.6.6.6 dhcp4: false 表示取消动态分配ip network:ethernets:e…...

[Linux]线程的互斥与同步

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

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

沙箱虚拟化技术虚拟机容器之间的关系详解

问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西&#xff0c;但是如果把三者放在一起&#xff0c;它们之间到底什么关系&#xff1f;又有什么联系呢&#xff1f;我不是很明白&#xff01;&#xff01;&#xff01; 就比如说&#xff1a; 沙箱&#…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤&#xff1a; 第一步&#xff1a; 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为&#xff1a; // 改为 v…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

MyBatis-Plus 常用条件构造方法

1.常用条件方法 方法 说明eq等于 ne不等于 <>gt大于 >ge大于等于 >lt小于 <le小于等于 <betweenBETWEEN 值1 AND 值2notBetweenNOT BETWEEN 值1 AND 值2likeLIKE %值%notLikeNOT LIKE %值%likeLeftLIKE %值likeRightLIKE 值%isNull字段 IS NULLisNotNull字段…...