截取页面中 ajax 请求
场景
有这样一个需求:
在一个使用 ajax 的网页中,浏览器使用 ajax 向服务端发出一个 HTTP 请求,我们希望获取到该请求的所有信息的同时,还能获取到服务器的返回数据。
在开始之前,我们先回顾一下 ajax 请求。
ajax 请求有如下两种形式:
$.ajax(url, settings) // 两个参数
$.ajax(settings) // 一个参数
第一种形式有两个参数,url 是一个字符串,表示请求地址,settings 是一个对象,包含了其他各种参数。
第二种形式只有一个参数,settings 中包含了 url 信息。
拦截方法
要拦截网页中的 ajax 请求,我们需要重写 $.ajax 函数。
主要思路为:
- 保存旧的函数,通过同名函数覆盖旧的函数,这样在调用
$.ajax请求时,就会执行我们新封装的$.ajax函数。 - 在重写了
$.ajax函数后,还需要执行原函数,保证原有逻辑不被改变 - 要获取服务端返回数据,还需要重写 success 回调函数,与
2做法相同
具体步骤为:
- 保存原来的 $.ajax 函数为 oldAjax
- 重写 $.ajax 函数覆盖 oldAjax 函数,并执行原 oldAjax 函数
- 在新的 $.ajax 函数中,保存 oldSuccess 回调函数
- 重写 success 回调函数,并执行 oldSuccess 回调函数
上面这段话听起来可能有点难以理解,
下面来看看代码。
代码
let oldAjax = $.ajax;
$.ajax = function(url, settings) {
// 参数形式为 $.ajax(url, setting) 时
if(typeof url === 'string') {
/**
* 在这里可以拦截到 ajax 请求所有数据,即:
* url、data、success、error...
*/
// 保存原回调函数 success
const success = settings[0].success;
// TODO: 处理相应逻辑
if(url === '/api/xx') {
// 重写 success 回调函数
settings[0].success() {
// 执行原回调函数
success.apply(this, arguments);
// TODO
}
// 执行原 ajax 函数
return oldAjax(url, settings);
}
}
// 调用参数形式为 $.ajax(settings) 时
// TODO: 处理相应逻辑
if(url.url === '/api/xxx') {
const success = url.success;
url.success = function() {
success.apply(this, agguments);
// TODO
}
return oldAjax(url);
}
}
总结:
我们拦截请求时,要遵守一个原则,那就是“不能破坏原来的逻辑”。所以,当我们重写了某个方法的时候,必须要在新的方法里去执行一次原来的方法。