思路
-
接收一个 Promise 实例的数组或具有 Iterator 接口的对象作为参数
-
这个方法返回一个新的 promise 对象,
-
遍历传入的参数,用Promise.resolve()将参数"包一层",使其变成一个promise对象
-
参数所有回调成功才是成功,返回值数组与参数顺序一致
-
参数数组其中一个失败,则触发失败状态,第一个触发失败的 Promise 错误信息作为 Promise.all 的错误信息。
实现
实现一
function promiseAll(promiseArray) {
return new Promise(function (resolve, reject) {
if (!Array.isArray(promiseArray)) {
throw new TypeError(`argument must be a array`)
}
let resolvedCounter = 0;
let promiseNum = promiseArray.length;
let resolvedResult = [];
for (let i = 0; i < promiseNum; i++) {
Promise.resolve(promiseArray[i]).then(
value => {
resolvedCounter++;
resolvedResult[i] = value;
if (resolvedCounter == promiseNum) {
return resolve(resolvedResult)
}
},
reason => {
return reject(error)
}
)
}
})
}
//------------------------- test---------------------------
let p1 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(1)
}, 1000)
})
let p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(2)
}, 2000)
})
let p3 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(3)
}, 3000)
})
promiseAll([p3, p1, p2]).then(res => {
console.log(res) // [3, 1, 2]
})
实现二
/**
* Promise.all
* @description 当这个数组里的所有promise对象全部变为resolve状态的时候,才会resolve, 当有一个promise对象变为reject状态时,就不再执行直接 reject
* @param {*} values promise对象组成的数组作为参数
*/
Promise.prototype.myAll = (values) => {
return new Promise(
(resolve, reject) => {
let resultArr = []
let count = 0
let resultByKey = (value, index) => {
resultArr[index] = value
if (++count === values.length) {
resolve(resultArr)
}
}
values.forEach(
(promise, index) => {
promise.then(
(value) => {
resultByKey(value, index)
},
reject
)
}
)
}
)
}
all的应用场景
一般来说,Promise.all 用来处理多个并发请求,将一个页面所用到的在不同接口的数据一起请求过来。直到完成所有的promise,才执行all的then方法。
拓展:实现promise队列
Promise.all().then()的用法,all()表示所有的操作均执行完成,再执行then()中的方法。而all()中的函数,不是顺序执行,而是同时执行。
如果希望then()之前的函数都是顺序执行的,可以考虑通过reduce函数来实现。
这就实现了一个promise队列
console.log("----------------------------------------")
const arr09 = [
() => new Promise(
(resolve) => {
setTimeout(() => {
console.log(10);
resolve(10);
}, 1000)
}
).then(res => { console.log(res) }),
() => new Promise(
(resolve) => {
setTimeout(() => {
console.log(20);
resolve(20);
}, 1000)
}
).then(res => { console.log(res) }),
() => new Promise(
(resolve) => {
setTimeout(() => {
console.log(30);
resolve(30);
}, 1000)
}
).then(res => { console.log(res) }),
() => (40)
]
const result09 = arr09.reduce(
(prev, next) => prev.then(next),
// 这里是为了new一个promise形成链式调用
Promise.resolve()
)
console.log(result09)
const createPromise = (id) => () =>
new Promise(resolve=>
setTimeout(()=>{
console.log("promise->"+id+":"+new Date());
resolve();
},1000)
)
var tasks = [createPromise(1),createPromise(2),createPromise(3)];
console.log(tasks);
var doTask = tasks.reduce((prev,next)=>prev.then(()=>next()),Promise.resolve());
doTask.then(()=>console.log("all done."));
其它写法
[1, 2, 3, 4, 5].reduce((pre, cur) => {
return pre.then(() => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(cur)
resolve()
}, 1000)
})
})
}, Promise.resolve())