深入理解Promise.all

Promise.all接收的promise数组是按顺序执行的还是一起执行的,也就是说返回的结果是顺序固定的吗?

目前有两种答案:

应该是同步执行的,但是这样就有效率问题了,如果想改成异步执行怎么办呢?

有些人认为结果是按顺序执行的,有些人认为结果顺序不确定。

那么我们根据实现来解密:

环境为:

vscode 1.20.1 node v8.9.0 npm v5.6.0

实验代码:

// 获取随机数,toFixed为四舍五入保留小数,0为保留整数,范围~1000 const getRandom = () => +(Math.random()*1000).toFixed(0); const asyncTask = (taskID) => new Promise( (resolve) => { // 随机获取一次0~1000的随机数 let timeout = getRandom(); // 打印出传递进来的ID号 taskID=1 start. console.log(`taskID=${taskID} start.`); // 设置计时时间,function()等价于 () => {...} setTimeout(function() { // 打印出执行的taskID,和timeout console.log(`taskID=${taskID} finished in time=${timeout}.`); // 异步成功执行 resolve(taskID) }, timeout); }); Promise.all([asyncTask(1),asyncTask(2),asyncTask(3)]) .then(resultList => { console.log('results:',resultList); });

实验结果如下:

第一次

taskID=1 start. taskID=2 start. taskID=3 start. taskID=2 finished in time=321. taskID=3 finished in time=506. taskID=1 finished in time=932. results: Array(3) [1, 2, 3]

第二次

taskID=1 start. taskID=2 start. taskID=3 start. taskID=1 finished in time=243. taskID=3 finished in time=305. taskID=2 finished in time=792. results: Array(3) [1, 2, 3]

第三次

taskID=1 start. taskID=2 start. taskID=3 start. taskID=3 finished in time=380. taskID=1 finished in time=539. taskID=2 finished in time=782. results: Array(3) [1, 2, 3]

补充知识介绍:

// toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。 NumberObject.toFixed(num) // num 必需。规定小数的位数,是 0 ~ 20 之间的值,包括 0 和 // 20,有些实现可以支持更大的数值范围。如果省略了该参数,将用 0 代替。

Promise构造函数只有一个参数,该参数是一个函数,被称作执行器,执行器有2个参数,分别是resolve()和reject(),一个表示成功的回调,一个表示失败的回调。

new Promise(function(resolve, reject) { setTimeout(() => resolve(5), 0) }).then(v => console.log(v)) // 5

记住,Promise实例只能通过resolve或者reject函数来返回,并且使用then()或者catch()获取,不能在new Promise里面直接return,这样是获取不到Promise返回值的。

由此可见,Promise.all 里的任务列表[asyncTask(1),asyncTask(2),asyncTask(3)],我们是按照顺序发起的。
但是根据结果来说,它们是异步的,互相之间并不阻塞,每个任务完成时机是不确定的,尽管如此,所有任务结束之
后,它们的结果仍然是按顺序地映射到resultList里,这样就能和Promise.all里的任务列表
[asyncTask(1),asyncTask(2),asyncTask(3)]一一对应起来。

深入理解Promise.all()

可能看到这里有些人没有清楚,为什么返回一个数组?

我们在来看一下这段代码:

Promise.all([asyncTask(1),asyncTask(2),asyncTask(3)]) .then(resultList => { console.log('results:',resultList); });

通常我们在使用异步的时候都是只有一个Promise,现在我们使用all()方法包装多个Promise实例。

语法很简单:参数只有一个,可迭代对象,可以是数组,或者Symbol类型等。

Promise.all(iterable).then().catch()

传入3个Promise实例:

Promise.all([ new Promise(function(resolve, reject) { resolve(1) }), new Promise(function(resolve, reject) { resolve(2) }), new Promise(function(resolve, reject) { resolve(3) }) ]).then(arr => { console.log(arr) // [1, 2, 3] })

那么我们回头想想应该明白了吧?

因为我们传入的是数组,那么返回的必须是数组,并且会将讲过进行映射。

Promise.race()

语法和all()一样,但是返回值有所不同,race根据传入的多个Promise实例,只要有一个实例resolve或者reject,就只返回该结果,其他实例不再执行。

我们简单看一下例子,返回结果为3,因为我们设置了定时器,第三个Promise执行的最快。

Promise.race([ new Promise(function(resolve, reject) { setTimeout(() => resolve(1), 1000) }), new Promise(function(resolve, reject) { setTimeout(() => resolve(2), 100) }), new Promise(function(resolve, reject) { setTimeout(() => resolve(3), 10) }) ]).then(value => { console.log(value) // 3 })

异步为什么使用箭头函数

这是我一直困惑的原因,我们将前面的例子进行改造一下。

如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/b4face1da67f44e5ae9c61cbc7b157ec.html