js高级异步编程(并发请求)

问题描述

我们知道js的一些异步编程的解决方案,比如最基本的回调函数、es6新增的promise以及es7新增的async和await。对此不熟悉的朋友可以参看我之前写的以一篇异步编程博客:js异步编程
现在提出一个更高阶的问题:
现在有一组异步请求rs,当rs中所有的异步操作执行完毕后再执行操作t
案例代码:

const getNumbers = () => Promise.resolve([1, 2, 3]);

const multi = num => new Promise((resolve, reject) => {
    setTimeout(() => {
        if (num) {
            resolve(num * num);
        } else {
            reject(new Error('num not specified'));
        }
    }, 1000);
});

解决方案

for循环

此方案的思路很简单:先通过getNumbers函数获取所需要的所有请求,然后遍历数组分别单独执行multi函数,等所有请求执行完毕后最后再执行操作t。
错误代码:

async function test() {
    console.log("开始执行异步操作!");
    const nums = await getNumbers();
    nums.forEach(async x => {
        const res = await multi(x)
        console.log(res);
    });
    console.log("执行操作t!");
}

执行此代码的结果为:
在这里插入图片描述
为什么会出现这种情况?
原因简单描述为:forEach 的回调函数是一个异步函数,异步函数中包含一个 await 等待 Promise 返回结果,相当于 for 循环执行了这个异步函数,所以是并行执行。
解决方案很简单,将forEach改为原始的for循环即可。
正确代码:

async function test1() {
    console.log("开始执行异步操作!");
    const nums = await getNumbers();
    for (let i = 0; i < nums.length; i++) {
        const res = await multi(nums[i]);
        console.log(res);
    }
    console.log("执行操作t!");
}

执行此代码的结果为:
在这里插入图片描述

并发请求

原生的js提供一个处理并发请求的方案:Promise.all()
此方案的思路:先通过getNumbers函数获取所需要的所有请求,然后遍历数组分别单独执行multi函数并获取所有的promise,使用Promise.all方法并发执行所有的promise,最后再执行操作t。
方案代码:

async function test2() {
    console.log("开始执行异步操作!");
    const nums = await getNumbers();
    const promises = [];
    nums.forEach(num => {
        promises.push(multi(num));
    });
    // 两种等价写法,选择其一即可
    const results = await Promise.all(promises);
    console.log(results);
    console.log("执行操作t!");
    // Promise.all(promises).then(results => {
    //     console.log(results);
    //     console.log("执行操作t!");
    // });
}

执行此代码的结果为:
在这里插入图片描述

小结

两种解决方案虽然都能解决一组异步请求的问题,但是其效果不完全一样,for循环的方式可以细致到精确处理一组异步请求里的每个请求,而Promise.all()只是一次性将一组异步请求全部处理并返回其结果。

结语

实际工作中可能会经常用到这种类似的并发请求问题,希望这篇博客能够帮助大家解答心中的疑惑。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值