关于使用axios发起网络请求的异步问题

我们都知道,发起网络请求这个任务,是一个异步任务。

大家可以看看以下代码中,网络请求中携带的参数是什么:

js 复制代码
const total = 500;
const params = {
    optionsA: "a",
    optionsB: "b",
    optionsC: "c",
    page:{
        currentPage: 1,
        pageSize: 20,
    }
};
const maxPage = Math.ceil(total / params.page.currentPage)
while(params.page.currentPage <= maxPage){
    // 发起网络请求
    axios.post('https://xxxxx.xxx.com/xxxx', params);
    // 页码增加
    params.page.currentPage++;
}

上述代码的本意是为了获取当前参数下所有的数据,所以会从第一页开始获取数据。但得到的输出结果却是下面的这个

js 复制代码
// 这里模仿的是在浏览器按下F12进入控制台中网络请求中的请求体
// 第一次请求
data:{
    optionsA: "a",
    optionsB: "b",
    optionsC: "c",
    page:{
        currentPage: 26,
        pageSize: 20,
    }
}

// 第二次请求
data:{
    optionsA: "a",
    optionsB: "b",
    optionsC: "c",
    page:{
        currentPage: 26,
        pageSize: 20,
    }
}

// 第三次请求
data:{
    optionsA: "a",
    optionsB: "b",
    optionsC: "c",
    page:{
        currentPage: 26,
        pageSize: 20,
    }
}

......

// 一共25次请求中的currentPage都是一样的

因为超出边界的缘故,所以每一次返回回来的数据都是null。

于是这里我就开始好奇了,为什么每次请求发出的currentPage都是26呢,为什么不是从1递增到25(对应上述我定义的maxSize)

我当然知道网络请求是异步的,但在过往我的认知中,这个异步是指其请求过程以及其请求结果的异步,也就是我们发出请求是同步的,而在请求回来以及后续处理的过程是属于异步的。

如果按这个思路走,那么就应该是从第1页递增到第25页才对啊。

我猜测一共有两种可能

  1. axios将请求的发送放到了异步当中
  2. xhrHttpRequest本身就是异步发送请求的

为了验证我的猜想,我就去翻了翻axios的源码

相关路径在node_modules/axios/lib

首先,我们顺着axios.methods的方向往下找,很快就找到了相关的源码,源码部分有兴趣的可以看看,懒得看得看我的文字也够了

js 复制代码
// node_modules/axios/lib/core/Axios.js

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  Axios.prototype[method] = function(url, data, config) {
    return this.request(utils.merge(config || {}, {
      method: method,
      url: url,
      data: data
    }));
  };
});

utils是一个工具库,有兴趣的可以去看看它的中文文档,utils中文文档|utils js中文教程|解析 | npm中文文档 (npmdoc.org)

上述代码的forEach和Array.prototype.map有点相似,return的值会成为新数组中的对应元素,当然这里没用到,这里是起到了遍历的操作。

顺着往下找,我们找到了this.request的定义

js 复制代码
// node_modules/axios/lib/core/Axios.js

/**
 * Dispatch a request
 *
 * @param {Object} config The config specific for this request (merged with this.defaults)
 */
Axios.prototype.request = function request(config) {
  /*eslint no-param-reassign:0*/
  // Allow for axios('example/url'[, config]) a la fetch API
  if (typeof config === 'string') {
    config = utils.merge({
      url: arguments[0]
    }, arguments[1]);
  }

  config = utils.merge(defaults, {method: 'get'}, this.defaults, config);
  config.method = config.method.toLowerCase();

  // Hook up interceptors middleware
  var chain = [dispatchRequest, undefined];
  var promise = Promise.resolve(config);

  this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
    chain.unshift(interceptor.fulfilled, interceptor.rejected);
  });

  this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
    chain.push(interceptor.fulfilled, interceptor.rejected);
  });

  while (chain.length) {
    promise = promise.then(chain.shift(), chain.shift());
  }

  return promise;
};

我们重点看21行及其之后的代码片段

可以看到,在21行定义了一个chain变量,这是作为一个类似于钩子函数队列的存在,也就是存放我们的请求拦截器和响应拦截器的地方,24行就是往队列首部添加请求拦截器,28行就是往队列尾部添加响应拦截器

其实从这里,就已经可以看出本篇文章所需要寻求的答案

最后我们在33行可以看到,从chain队列中取任务的操作通过promise的then方法放入到了微任务队列中,并且通过then链式调用,最后调用到我们的dispatchRequest方法(发送请求的方法,由原生xhrHttpRequest或者http模块封装)

所以通过以上研究可以明白,axios中的异步,这是真的从开始到结束,都是在异步完成的,再回到一开始的问题,如果想要并发多个请求,可以更改代码为以下内容

js 复制代码
const total = 500;
const page = 1;
const pageSize = 20;
const maxPage = Math.ceil(total / pageSize)
while(page <= maxPage){
    // 定义参数
    const params = {
        optionsA: "a",
        optionsB: "b",
        optionsC: "c",
        page:{
            currentPage: page,
            pageSize: pageSize,
        }
    };
    // 发起网络请求
    axios.post('https://xxxxx.xxx.com/xxxx', params);
    // 页码增加
    page++;
}

好了我要加班去了,拜拜咯,喜欢的话给我点个赞,收藏,评论一下都好,让我开心开心谢谢你们!!

如果有不对的,欢迎大佬们多指导一下!!!

相关推荐
console.log('npc')22 分钟前
Git 冲突与 AI 协助指南
前端·人工智能·git·大模型
爱学堂IT分享2 小时前
Cesium可视化系统实战课程-Cesium教程学习
前端
糖墨夕2 小时前
理解大语言模型:Agent 的“大脑”
前端·agent
Rain的Java大神之路2 小时前
JavaWeb开发如何解决跨域问题
java·前端·后端·nginx·web安全·面试·运维开发
cpolar技术支持2 小时前
浏览器也能跑本地 AI:用 Transformers.js + WebGPU 做一个最小推理 Demo,cpolar 给同事远程体验
前端·ai·cpolar·webgpu·transformers.js
计算机魔术师4 小时前
OpenAI 发布 GPT-6 Astra:多项基准刷新纪录, cybersecurity 能力达 Critical 阈值
前端
xy34534 小时前
Axure9.0中继器遮罩实现方法
前端·ui·html·axure·原型·产品设计
风骏时光牛马4 小时前
智能任务自动化协同AI工作流
前端
IT_陈寒4 小时前
Python的多线程居然是个假把式?搞清GIL让我少熬三天夜
前端·人工智能·后端
宿6744 小时前
vue3-config
前端·javascript·vue.js