关于使用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++;
}

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

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

相关推荐
恋猫de小郭1 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅8 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60619 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了9 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅9 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅10 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment10 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅10 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊10 小时前
jwt介绍
前端