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

axios取消请求逻辑

axios是一款基于xml和 http请求对象 封装的请求库, 本文梳理其请求中断逻辑

1. 中断函数的使用: 

        

// 引入axios
const axios = require('axios');

// 创建取消令牌的源
const cancelTokenSource = axios.CancelToken.source();

// 发起一个请求
axios.get('https://example.com/api/data', {
  cancelToken: cancelTokenSource.token
}).then(response => {
  console.log('请求成功:', response.data);
}).catch(error => {
  if (axios.isCancel(error)) {
    console.log('请求被取消:', error.message);
  } else {
    // 处理其他错误
    console.error('请求出错:', error);
  }
});

// 如果需要取消请求
cancelTokenSource.cancel('取消请求,例如用户导航到其他页面');

2.  cancelToken的source作用如下

CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;

 new 出cancelToken的实例,定义executor函数,利用executor的形参获取到c, c为取消函数

3. cancelToken代码如下

// 文件路径 Axios/lib/cancel/CancelToken.js

// ...

/**
 * A `CancelToken` is an object that can be used to request cancellation of an operation.
 *
 * @class
 * @param {Function} executor The executor function.
 */
function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }

  var resolvePromise;

  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  var token = this;

  // eslint-disable-next-line func-names
  this.promise.then(function(cancel) {
    if (!token._listeners) return;

    var i;
    var l = token._listeners.length;

    for (i = 0; i < l; i++) {
      token._listeners[i](cancel);
    }
    token._listeners = null;
  });

  // eslint-disable-next-line func-names
  this.promise.then = function(onfulfilled) { // ...
  };

  executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
}

// ...


cancelToken类会立即执行 executor函数,将取消方法作为实参传递, source中cancel接到的形参便是executor中的cancel实参, 外部执行cancel执行的是resolvePromise方法

 executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });

resolvePromise 用于存放cancelToken类中promise的resolve, promise用于控制中断相关操作的执行。 当resolvePromise执行, promsie被放行,则会执行cancelToken中的listeners

  var resolvePromise;

  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });
 this.promise.then(function(cancel) {
    if (!token._listeners) return;

    var i;
    var l = token._listeners.length;

    for (i = 0; i < l; i++) {
      token._listeners[i](cancel);
    }
    token._listeners = null;
  });

listenters是注册的中断函数,注册方法如下: 

// 文件路径 Axios/lib/cancel/CancelToken.js

// ...

/**
 * Subscribe to the cancel signal
 */

CancelToken.prototype.subscribe = function subscribe(listener) {
  // reason 值不为 undefined 说明该请求已取消,可直接调用 listener
  if (this.reason) {
    listener(this.reason);
    return;
  }

  if (this._listeners) {
    this._listeners.push(listener);
  } else {
    this._listeners = [listener];
  }
};

// ...


4. 核心请求方法

// Axios/lib/adapters/xhr.js

// ...
    if (config.cancelToken || config.signal) {
      // Handle cancellation
      // eslint-disable-next-line func-names
      onCanceled = function(cancel) {
        if (!request) {
          return;
        }
        reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
        request.abort();
        request = null;
      };

      config.cancelToken && config.cancelToken.subscribe(onCanceled);
      if (config.signal) {
        config.signal.aborted ? onCanceled() : config.signal.addEventListener('abort', onCanceled);
      }
    }
    
// ...

在走请求流程时,如果当前请求配置有cnacelToken, 定义onCanceled 中断函数,并通过subscribe注册到cancelToken类中, 等待resolvePromise 放行promise, 从而执行中断逻辑。

总结

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

 回顾一下source方法,

CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel
  };
};

source返回了两个属性,

cancel是中断方法, 用于用户手动中断请求,

source.cancel('取消请求,例如用户导航到其他页面');

token为cancelToken实例, 显式的声明在axios请求上

axios.get('https://example.com/api/data', {
  cancelToken: cancelTokenSource.token
}).then

        当axios获取到cancelToken时,会定义中断请求的具体逻辑,通过cancelToken的 subscribe 进行订阅

        cancelToken类本身存在一个promise, resolve方法被存放在变量中, 当手动触发cancel方法时, resolve会放行, promsie.then会执行先前订阅的中断逻辑。 

        而中断逻辑则是给当前请求的promsie一个reject, 并且手动abort网络请求

 reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
 request.abort();
 request = null;


http://www.kler.cn/news/365062.html

相关文章:

  • 重生之“我打数据结构,真的假的?”--3.栈和队列(无习题)
  • 【MySQL数据库】MySQL高级语句(SQL语句进阶版)
  • 什么是代码注入,如何防御?
  • 新增Python运行环境、支持病毒扫描和计划任务短信告警,1Panel开源面板v1.10.20 LTS版本发布
  • react18中的函数组件底层渲染原理分析
  • 数据类型【MySQL】
  • html+css+js实现Badge 标记
  • Mysql树形结构表-查询所有父级数据(模糊查询)
  • Android14 和android12 在锁屏界面Keyguard输错5次密码后倒计时30秒时重启手机不显示倒计时
  • SOLIDWORKS正版软件的渠道分别是哪些,如何选择?
  • 使用RNN、LSTM和Transformer进行时间序列预测
  • AJAX 实例:深入解析与实战应用
  • 代码随想录算法训练营Day09 | 151.翻转字符串里的单词、卡码网:55.右旋转字符串、28. 实现 strStr()、459.重复的子字符串
  • AUTOSAR CP 中 BswM 模块功能与使用介绍(2/2)
  • python主流框架Django:ORM框架关联查询与管理器
  • 关于Linux自带的python2.6.6升级到2.7.5版本步骤详解
  • 在银河麒麟系统中Qt连接达梦数据库
  • Python爬虫:自动化获取商品评论数据
  • 纯血鸿蒙的未来前景
  • 7款视频转换器大测评!哪款是最适合你的视频格式转换器?
  • spring boot yml文件中引用*.properties文件中的属性
  • 雷池社区版那么火,为什么站长都使用雷池社区版??
  • 我们可以用微服务创建状态机吗?
  • 边缘计算路由网关R40钡铼技术3LAN口1WAN口Modbus协议
  • 系统架构设计师教程 第6章 6.4 应用程序域数据库的交互 笔记
  • ASP.NET Core 8.0 中使用 Hangfire 调度 API