- [1. 一、ajax-hook 是什么](#1-一ajax-hook-是什么)- [2. 二、核心功能](#2-二核心功能)- [3. 三、安装与引入](#3-三安装与引入)- [4. 四、核心 API 与使用示例](#4-四核心-api-与使用示例)- [5. 五、实战场景示例](#5-五实战场景示例)- [6. 六、注意事项](#6-六注意事项)- [7. 七、总结](#7-七总结)
1. 一、ajax-hook 是什么
ajax-hook 是一个轻量、无侵入的 JavaScript 库,核心是拦截浏览器原生 XMLHttpRequest(XHR),在不改动业务代码的前提下,劫持所有 AJAX 请求的发起、响应、错误与超时等环节,统一处理请求/响应逻辑。
• 作者:wendux(GitHub 开源) • 原理:重写全局 XMLHttpRequest 构造函数,用代理对象接管请求,内部调用原生 XHR。
2. 二、核心功能
1. 全局拦截所有 AJAX 请求(包括原生 XHR、jQuery、axios 等基于 XHR 的请求)。 2. 请求阶段处理:修改 URL、添加请求头/参数、签名校验、中止请求。 3. 响应阶段处理:修改响应数据、统一解析、状态码拦截(如 401 登录过期跳转)。 4. 错误/超时捕获:统一日志、重试逻辑、错误提示。 5. 请求统计/监控:接口调用次数、耗时、成功率统计。 6. 数据模拟:开发环境拦截接口,返回 Mock 数据。 7. 动态启停:随时开启/关闭拦截,恢复原生 XHR。
3. 三、安装与引入
3.1. CDN 引入(浏览器直接用)
<scriptsrc="https://unpkg.com/ajax-hook@2.0.3/dist/ajaxhook.min.js"></script><!-- 全局会挂载 ah 对象 -->3.2. NPM 安装(工程化项目)
npm install ajax-hook --save// ES6import { proxy, unProxy } from'ajax-hook';// CommonJSconst { proxy } = require('ajax-hook');4. 四、核心 API 与使用示例
4.1. 基础用法:proxy(推荐,简洁)
proxy(hooks) 拦截所有请求,提供 onRequest、onResponse、onError 三个钩子。
import { proxy } from'ajax-hook';// 开启拦截proxy({// 请求发起前(可修改 config)onRequest: (config, handler) => {console.log('请求前:', config);// 示例1:给所有 GET 请求加时间戳if (config.method === 'GET') { config.url += (config.url.includes('?') ? '&' : '?') + '_t=' + Date.now(); }// 示例2:统一添加请求头(如 Token) config.headers = { ...config.headers, Authorization: 'Bearer xxx' }; handler.next(config); // 继续请求// handler.abort(); // 中止请求 },// 响应成功后(可修改 response)onResponse: (response, handler) => {console.log('响应成功:', response);// 示例1:统一解析 JSONtry { response.data = JSON.parse(response.response); } catch (e) {}// 示例2:拦截登录过期(假设 code=401)if (response.data?.code === 401) {console.log('登录过期,跳转登录页');window.location.href = '/login';return; // 终止响应,不回传给业务 } handler.next(response); // 继续传递响应 },// 请求错误(超时、网络错误,不含 404/500)onError: (err, handler) => {console.error('请求错误:', err);// 示例:统一错误提示alert('网络异常,请稍后重试'); handler.next(err); }});// 关闭拦截(恢复原生 XHR)// import { unProxy } from 'ajax-hook';// unProxy();4.2. 细粒度拦截:hookAjax(底层,可控性强)
hookAjax(obj) 直接拦截 XHR 的open、send、onload、onreadystatechange 等方法/回调。
// CDN 引入后直接用 ah.hookAjaxah.hookAjax({// 拦截 xhr.open(method, url, async, user, password)open: (args, xhr) => {const [method, url] = args;console.log('open:', method, url);// 修改 URL args[1] = url.replace('/api', '/proxy-api'); },// 拦截 xhr.send(data)send: (args, xhr) => {console.log('send 数据:', args[0]); },// 拦截响应就绪onreadystatechange: (xhr) => {if (xhr.readyState === 4 && xhr.status === 200) {console.log('原始响应:', xhr.responseText);// 修改响应(只读属性可通过 updateXhr 修改) xhr.updateXhr('responseText', JSON.stringify({code: 0,data: JSON.parse(xhr.responseText) })); } }});// 取消细粒度拦截// ah.unHookAjax();5. 五、实战场景示例
5.1. 场景1:开发环境 Mock 接口
proxy({onResponse: (response, handler) => {// 拦截 /api/user 接口if (response.config.url.includes('/api/user')) {// 返回模拟数据 response.response = JSON.stringify({code: 0,data: { id: 1, name: '测试用户', age: 25 } }); } handler.next(response); }});5.2. 场景2:统一请求签名
import md5 from'md5';proxy({onRequest: (config, handler) => {// 生成签名:url + 时间戳 + 密钥 做 md5const timestamp = Date.now();const sign = md5(config.url + timestamp + 'your-secret-key');// 添加到请求头 config.headers = { ...config.headers, timestamp, sign }; handler.next(config); }});5.3. 场景3:统计接口耗时
proxy({onRequest: (config, handler) => { config.startTime = Date.now(); handler.next(config); },onResponse: (response, handler) => {const cost = Date.now() - response.config.startTime;console.log(`接口 ${response.config.url} 耗时:${cost}ms`); handler.next(response); }});6. 六、注意事项
1. 拦截范围:仅拦截 XHR,fetch API 不拦截(需单独处理 fetch)。 2. 顺序:需在所有请求发起前执行 proxy/hookAjax(如入口文件最先引入)。3. 兼容性:支持 IE10+ 及所有现代浏览器。 4. 恢复原生:不用时务必调用 unProxy/unHookAjax,避免污染全局 XHR。
7. 七、总结
ajax-hook 是前端请求治理的利器,用最简单的方式实现全局请求拦截,适合做统一鉴权、日志监控、数据 Mock、错误处理等基础能力,大幅减少重复代码。
更多详细内容,请微信搜索“前端爱好者“, 戳我 查看 。
夜雨聆风