我知道我们不能简单地做类似的事情:
myArray.forEach(async x => await asyncOperation())
编辑:我知道这是有效的,但是我需要保持正确的顺序
如果必须使用异步操作遍历数组,则必须执行以下操作:
await Promise.all(myArray.map(x => asyncOperation()))
但是,我需要在同一迭代中执行两个异步操作。我知道另一种替代方法是只使用.reduce
,它看起来像这样:
await myArray.reduce((p, el) => {
return p.then(() => {
return somePromise(el)
.then(res => {
return anotherPromise(res)
})
})
}, Promise.resolve())
但是我避免嵌套promise,并希望仅使用async/await
保留它。所以无论如何,我的问题是,遍历需要经过两个promise的数组的最佳等待时间是什么?
答案 0 :(得分:0)
您可以在单独的函数中执行彼此依赖的异步代码,该函数在地图中调用,然后将地图包装在Promise.all中。
const doAsyncStuff = async (x) => {
const firstValue = await fakeLongTask1();
const finalValue = await fakeLongTask2(firstValue);
return finalValue;
}
Promise.all(myArray.map(x => {
doAsyncStuff(x);
}));
这将解雇所有任务,但是等待彼此依赖的长任务,然后一旦完成,Promise.all就解决了。
答案 1 :(得分:0)
您可以将async循环与递归函数一起使用,即使我不能使用async / await,我通常也采用这种方式编写代码
a
这应该是一种模式,我一直在这样做,但是通常看起来像这样(我仍然手动编写一些ES5代码)。
return (async function next() {
var item = arr.shift();
if (shift) {
var res = await doSomething(item);
await doSmethingElse(res);
next();
}
})();
如果要累积doSmethingElse的结果,只需将其添加到数组中,然后传递以与async / await示例一样进行解析。
return new Promise(resolve) {
(function next() {
var item = arr.shift();
if (item) {
doSomething(item).then(doSmethingElse).then(next);
} else {
resolve();
}
})();
});
答案 2 :(得分:-1)
无耻插入插件,我建议使用npm package bs-better-stream,它专门研究异步流/数组。
例如,它可能很简单:
const stream = require('bs-better-stream');
let s = stream()
.write(...myArray)
.map(el => somePromsie(el))
.wait() // or waitOrdered() to preserve original order
.map(res => anotherPromise(res))
.wait();
如果要转换回原始数组,它会稍微冗长一些,因为您需要等待两组承诺都可以解决。但是它仍然比.reduce
或(await Promise.all(...)).map
更具可读性:
const stream = require('bs-better-stream');
let somePromise = a => Promise.resolve(a * 2);
let anotherPromise = a => Promise.resolve(-a);
let x = async myArray => {
let promises = stream()
.write(...myArray)
.map(el => somePromise(el));
let promises2 = promises
.wait()
.map(res => anotherPromise(res));
await promises.promise;
return promises2.promise; // -2, -4, -6, -8
}
x([1, 2, 3, 4]).then(a => console.log(a));
此方法的另一个优点是,它允许所有异步功能并行发生。即第二组承诺不必等待所有第一组承诺完成。
答案 3 :(得分:-1)
async
/ await
很棒,但是它们并不是所有使用承诺的代码的100%替代。有时(例如,当您需要使用Promise.all
时),您会需要将承诺本身用作值,而不是在async
/ await
内部秘密使用。
有 种方式可以避免这种情况,例如避开ES6 map
和其他数组迭代方法,而是使用for
循环...但通常这样做是...治愈比疾病还糟。只是使用诺言。
编辑:
这是一个基于评论反馈的基本示例。假设您有两个(或多个)URL,并且想获取第一个(然后返回),然后获取下一个,一旦全部获取,则执行其他操作。如果您尝试与ES6数组方法同步执行此操作,即使您使用async
/ await
,也将无法使用:
const urls = ['www.example.com/1', 'www.example.com/2'].
var promises = urls.map(async url => await fetch(url));
Promise.all(promises).then(doSomethingElse);
该代码将实际执行的操作是立即获取所有URL。 不会等待获取第二个,直到第一个完成。
为此,您可以 可以将async
/ await
与for
循环一起使用,并避免使用ES6(大概在{{1 }}函数):
async
...但是您正在使用const urls = ['www.example.com/1', 'www.example.com/2'].
const pageHtml = [];
for (var i = 0; i < promises.length; i++) {
const url = urls[i];
const html = await fetch(url));
pageHtml.push(html);
}
doSomethingElse(); // no need for Promise.all!
循环,就像1999年一样; ick!我认为更好的解决方案是使用现代Javascript,但不要对所有 使用for
/ async
。
最多使用 个关键字,但是随后当您需要使用await
时,可以使用递归函数(如果需要“ fetch#1 AFTER#2”部分;参见@jcubic的答案以获取可能的实现),或者如果您不只是这样做:
Promise.all
是的 是避免使用const urls = ['www.example.com/1', 'www.example.com/2'].
var promises = urls.map(fetch);
Promise.all(promises).then(doSomethingElse);
/ async
并使用数组或Promise对象
直接使用await
...,但是代码简短明了,可以满足您的要求。您不必总是使用这些关键字。
答案 4 :(得分:-1)
这是我有时使用的功能,可以按顺序遍历长任务。
var arr = ['do', 're', 'mi', 'fa', 'so', 'la', 'ti'];
const f1 = () => new Promise(d => setTimeout(d, 250));
const f2 = () => new Promise(d => setTimeout(d, 250));
(async() => {
await asyncLoop(arr, async(itm, idx, fin) => {
console.log('doing something async with ', itm);
await f1();
console.log('doing something async with ', itm, ' again');
await f2();
fin(); // start the next loop
});
console.log('done looping');
})();
function asyncLoop(items, loopBody) {
return new Promise(f => {
let done = arguments[2] || f;
let idx = arguments[3] || 0;
let cb = items[idx + 1] ? () => asyncLoop(items, loopBody, done, idx + 1) : done;
loopBody(items[idx], idx, cb);
});
}
为方便起见,它位于https://www.twilio.com/docs/voice/api/call#update-a-call-resource上。