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

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

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

相关推荐
默_笙22 分钟前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯34 分钟前
标签打印软件怎么对接 Excel 数据
前端·excel
一个风轻云淡2 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u0111026752 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说3 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa3 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端
deli0073 小时前
DLA 枝晶生长实测:5000 个粒子集体停摆之后,分形维数收敛到 1.70
前端
IT_陈寒3 小时前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端
可乐鸡翅yeah_4 小时前
video.js 集成 hls.js 开发 M3U8 播放器,新手高频踩坑
开发语言·前端·javascript·后端·ecmascript·m3u8·音视频在线播放
程序猿追4 小时前
HarmonyOS 6 上做个极简浏览器:Web 组件 + 前进后退 + 加载进度
前端·华为·harmonyos