await 在for循环中的使用。
以前await必须与 async配对使用。 现在 Chrome 86已经支持,直接在for循环中单独使用await了。
for(let i=0; i< 3;i++){
const result = await i+1;
console.log(result)
}
await与 for of
for await (let num of [1,2,3]) {
console.log(num);// 1,2,3
}
await 在forEach,map, reduce循环中不起作用
const fetch = (forceTrue) =>
new Promise((resolve, reject) => {
if (Math.random() > 0.2 || forceTrue) {
resolve("success");
} else {
reject("error");
}
});
const result = [];
[0, 1, 2].forEach(async () => {
const value = await fetch(true);
result.push(value);
});
console.log(result); // 返回 []
forEach愿源码实现中通过 while 循环里面多次调用callback.call(T, kValue, k, O);来实现的, 由于它前面没有 await, 所以每次循环执行到这里的时候并没有等待它执行完,最后打印 result 的时候就是空数组了。
解决方法
可以通过在最外层加一层自执行的async 函数 fix:
(async function(){
await [0, 1, 2].forEach(async () => {
const value = await fetch(true);
result.push(value);
});
})()
实现多个 promise 同步执行,不管有没有抛出错误,都把结果收集起来
- 使用 for 循环解决
Promise.myAll = function (promiseArr) {
const len = promiseArr.length;
const result = [];
let count = 0;
return new Promise((resolve, reject) => {
for (let i = 0; i < len; ++i) {
promiseArr[i].then((res) => {
result[i] = res;
++count;
if (count >= len) {
resolve(result);
}
}, (err) => {
result[i] = err;
++count;
if (count >= len) {
resolve(result);
}
});
}
});
}
// test
const fetch = (forceTrue) => new Promise((resolve, reject) => {
if (Math.random() > 0.2 || forceTrue) {
resolve('success');
} else {
reject('error');
}
});
Promise.myAll([fetch(), fetch(), fetch()])
.then(res => console.log(res)); // ["success", "success", "error"]
Hack
如果注意到 promise 的「then 方法和 catch 方法都会返回一个 promise」的话,就可以用下面的简单方法:
Promise.myAll = function (promiseArr) {
// 就这一行代码!
return Promise.all(promiseArr.map(item => item.catch(err => err)));
}
// test
const fetch = (forceTrue) => new Promise((resolve, reject) => {
if (Math.random() > 0.2 || forceTrue) {
resolve('success');
} else {
reject('error');
}
});
Promise.myAll([fetch(), fetch(), fetch()])
.then(res => console.log(res)); // ["error", "error", "success"]