终止已被发出的请求

61 篇文章 1 订阅

Axios中取消请求的实现

Axios :主流的、基于 XMLHttpReqeust、promise 的 HTTP 库

如何实现 – cancelToken

// 创建取消令牌的生成器对象
const CancelToken = axios.CancelToken;
// 获取令牌对象
const source = CancelToke.source();
axios.get('/url/111', {
  cancelToken: source.token
});
// 2秒后取消请求
setTimeout(() => {
  source.cancel();
}, 2000);

实现思路

想要实现取消某个请求,我们需要为该请求配置一个 cancelToken ,然后在外部调用一个 cancel 方法。

请求的发送是一个异步过程,最终会执行 xhr.send 方法,xhr 对象提供了 abort 方法,可以把请求取消。因为我们在外部是碰不到 xhr 对象的,所以我们想在执行 cancel 的时候,去执行 xhr.abort 方法。

我们在 xhr 异步请求的过程中,插入一段代码,当我们在外部执行 cancel 函数的时候,会驱动这段代码的执行,然后执行 xhr.abort 方法取消请求。

取消请求必然是个异步的操作,自然想到用 Promise 实现异步,也就是在 cancelToken 中保存一个 pending 状态的 Promise 对象,然后当我们执行 cancel方法的时候,能够访问这个 Promise 对象,把它从 pending 状态变成 resolved 状态,这样我们就可以在 then 函数中去实现取消请求的逻辑。

// 创建Promise,返回开关cancel
function source () {
  let cancel;
  const promise = new Promise((resolve) => {
    cancel = resolve;
  }
  return {
    token: promise  // pending状态的promise
    cancel,      // 使上面的promise变成resolve状态
  }
}
// 发请求
function axios_get (config) {
    const xhr = new XMLHttpRequest(),
    method = "GET",
    url = "https://xxxx/";
    xhr.open(method, url, true);
    xhr.send();
    if (config.cancelToken) {
      config.cancelToken.then(() => {
          xhr.abort();
      })
    }
}
// 代码执行
const source = source();
axios_get({ cancelToken: source.token });
setTimeout(() => {
  source.cancel();
}, 5000)

XMLHttpRequest.abort

ajax(XMLHttpReqeust)终止请求的方式:XMLHttpRequest.abort()
如果该请求已被发出,XMLHttpRequest.abort() 方法将终止该请求。当一个请求被终止,它的 readyState 将被置为 XMLHttpRequest.UNSENT (0),并且请求的 status 置为 0

var xhr = new XMLHttpRequest(),
    method = "GET",
    url = "https://xxx/";
xhr.open(method, url, true);

xhr.send();

if (OH_NOES_WE_NEED_TO_CANCEL_RIGHT_NOW_OR_ELSE) {
  xhr.abort();
}
var request;
if (request) {
  request.abort();
}
request = $.ajax({
  // 各种参数
})

取消promise

  • 方案一 借助Promise.reject
function getPromise (callback) {
  let _resolve, _reject;
  const promise = new Promise((res, rej) => {
    _resolve = res;
     _reject = rej;
    callback && callback(res, rej);
    return {
      promise,
      abort: () => {
        _reject({ message: "promise aborted" })
      }
    }
  })
}

function runCallback (resolve, reject) {
    setTimeout(() => {
        resolve(12345);
    }, 5000)
}
const { promise, abort } = getPromise(runCallback);
promise.then(/*...*/).catch(/*...*/)
abort()
  • 方案二 借助Promise.race

Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝

function getPromiseWithAbort (p) {
  let obj = {};
  let p1 = new Promise((resolve, reject) => {
    obj.abort = reject;
  });
  obj.promise = Promise.race([p, p1]);
  return obj
}
const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(12345);
    }, 5000)
});
const promiseObj = getPromiseWithAbort(promise)
promiseObj.promise.then(/*...*/).catch(/*...*/)
obj.abort('取消执行')

AbortSignal

AbortSignal 是一个实验性的API,可以实例化一个信号对象(signal object)
AbortController 可以实例化一个信号对象的控制器,它就像遥控器一样,可以控制中断的信号
AbortSignal的出现使promise从语义上变为可中止的。并且,只要符合规范,所有异步操作都能变为 可中止的。

// 初始化控制器
const controller = new AbortController();
const signal = controller.signal;

// 监听abort事件
signal.addEventListener('abort', () => {
  console.log("中断信号发出");
})

// 控制器发出中断信号
controller.abort()
console.log("是否中断:", signal.aborted)
// 依次打印  中断信号发出、 是否中断:true

AbortSignal在fetch中的应用
fetch API 中已经集成了AbortSignal,使用时需要将controller中的信号对象作为signal参数传递给fetch,当调用controller.abort()后,fetch的promise会变为AbortError DOMException reject

const controller = new AbortController()
fetch('xxx', {
  signal: controller.signal
}).then(() => {
}).catch(err => {
  if (err.name === '') {
  // 中止信号
  } else {
  // 其他错误
  }
})

AbortSignal与任何异步操作结合

不仅适用于fetch,任何异步操作只要符合如下规范,都可以与Abort Error集成

  • 将AbortSignal 作为API的signal参数传入
  • 约定如果API返回的promise变为Abort Error DOMException reject则代表操作被中止
  • 如果signal.aborted === true 则立刻让promise变为reject
  • 观测AbortSignal状态的变化
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用jQuery的ajax请求预处理函数(beforeSend)来实现这个功能。在预处理函数中发送一个密码验证的ajax请求,如果错误则调用jQuery的ajax请求终止函数(abort)来终止所有请求。 示例代码: ```javascript $.ajaxSetup({ beforeSend: function(xhr) { // 发送密码验证请求 $.ajax({ url: 'verify_password.php', type: 'POST', data: {password: '123456'}, success: function(response) { if (response.error) { // 验证失败, 终止所有请求 xhr.abort(); } } }); } }); ``` 这样,所有jQuery发出的ajax请求都会先经过密码验证,如果验证失败就会终止请求。 ### 回答2: 要实现在加载所有请求之前进行一次ajax请求密码验证,并在密码错误时终止所有请求,我们可以使用jQuery的ajax全局事件和Deferred对象来实现。 首先,在页面加载完成后,可以使用$(document).ready()函数,绑定一个ajaxStart事件处理函数,在该函数中进行密码验证的ajax请求。如下所示: $(document).ready(function(){ // 验证密码的ajax请求 $.ajax({ url: '验证密码的URL', type: 'POST', data: {password: '密码'}, success: function(response){ // 验证成功 if(response.success){ // 发送ajax请求 $.ajaxSetup({ beforeSend: function(){ // 请求之前的处理 } }); }else{ // 验证失败,终止所有ajax请求 $(document).ajaxSend(function(event, xhr, settings){ xhr.abort(); }); } } }); }); 在ajaxStart事件处理函数中,我们可以使用$.ajaxSetup()函数来设置在发送每个ajax请求之前的处理函数。可以在beforeSend函数中进行一些预处理操作。 如果密码验证失败,我们可以使用$.ajaxSend()函数来绑定一个ajaxSend事件处理函数,该函数中使用xhr.abort()方法终止所有的ajax请求。 通过以上方式,我们可以在加载所有请求之前进行一次密码验证的ajax请求,并且在密码错误时终止一切请求。 ### 回答3: 在jQuery中,可以通过使用全局的ajax事件处理函数来设置在加载所有请求之前进行一次ajax请求密码验证,并在验证错误时终止一切请求。 具体的实现步骤如下: 1. 首先,在页面加载完成之后,绑定一个全局的ajax事件处理函数。 ```javascript $(document).ready(function() { $(document).ajaxSend(function(event, xhr, settings) { // 在发送任何ajax请求之前执行的代码 }); }); ``` 2. 在ajax事件处理函数中进行密码验证的ajax请求,并在验证错误时终止一切请求。 ```javascript $(document).ready(function() { $(document).ajaxSend(function(event, xhr, settings) { // 在发送任何ajax请求之前执行的代码 // 发送密码验证的ajax请求 $.ajax({ url: "验证密码的接口url", type: "POST", data: { password: "密码" }, success: function(response) { // 验证密码成功,继续发送之前的ajax请求 xhr.setRequestHeader('Authorization', 'Bearer ' + response.token); // 设置Token等请求头 xhr.setRequestHeader('X-Csrf-Token', response.csrfToken); // 设置CSRF Token等请求头 xhr.setRequestHeader('Accept', 'application/json'); // 设置请求头 $.ajax(settings); // 发送之前的ajax请求 }, error: function(xhr, textStatus, errorThrown) { // 验证密码失败,终止一切请求 xhr.abort(); console.error("密码验证失败,请求终止!"); } }); }); }); ``` 在上述代码中,我们在ajax事件处理函数中先发送一个密码验证的ajax请求。在成功验证密码后,我们可以设置之前请求需要的请求头等信息,并继续发送之前设置的ajax请求。而当验证密码失败时,我们使用`xhr.abort()`方法终止当前的请求,并打印错误信息。 需要注意的是,上述代码中的密码验证接口的URL需要根据实际情况进行替换,同时也需要根据实际情况设置正确的请求参数和请求头。 绑定全局的ajax事件处理函数后,在后续的任何ajax请求发送之前都会先执行密码验证的ajax请求,只有当密码验证成功后才会继续发送之前设置的ajax请求,否则会终止所有请求

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值