2017-10-18 37 views
2

考虑下面简单的代码代码:等待异步函数完成内部地图

await Promise.all(arrayOfObjects.map(async (obj) => { 
    return await someAsyncFunctionOnObj(obj); 
})); 

我的问题是,arrayOfObjects,并someAsyncFunctionOnObj,在执行占用太多的内存,因为环没有按”等待执行完成,而是每次调用someAsyncFunctionOnObj(obj),并等待直到全部解决,而不是必需的顺序,这会导致OOM崩溃。 Iv'e尝试使用递归异步函数,它可以解决订单问题,但仍会导致OOM崩溃。

我要实现的是一个同步的循环流动,这意味着

await someAsyncFunctionOnObj(obj1); // wait for it to finish 
await someAsyncFunctionOnObj(obj2); // wait for it to finish 
... 

如何正确地执行它有什么建议?

+0

首先,它应该是'返回等待someAsyncFunctionOnObj(OBJ);'但你真的,如果你使用'Promise.all'不需要异步/ AWAIT。或者只是'等待Promise.all(arrayOfObjects.map(someAsyncFunctionOnObj));' – dfsq

+0

@dfsq是的,我只是显示了基本概念。 – vrachlin

+0

为什么你使用Promise.all当你想要链接它们? – Robert

回答

2

async function queueAsyncFns(fns) { 
    const values = []; 

    await fns.reduce((previous, current, index, array) => { 
    const thenable = index === 1 ? previous() : previous; 
    return thenable.then(value => { 
     values.push(value); 
     return index === array.length - 1 ? current().then(value => values.push(value)) : current(); 
    }); 
    }); 

    return values; 
} 

const anArray = [1, 2, 3]; 
const doSomething = async (id) => await fetch(`https://jsonplaceholder.typicode.com/users/${id}`).then(res => res.json()); 

queueAsyncFns(anArray.map((val) =>() => doSomething(val))).then((val) => console.log(val)); 

上述功能应该可以解决您的问题。下面简要介绍它的功能:

queueAsyncFns接受一组返回调用异步函数结果的函数。通过调用每个函数并将Promise返回到reducer的下一个调用来减少此数组。每次迭代时,异步调用的值将被累加到一个名为values的数组中,该数组在迭代完所有项后返回。

通过查看运行示例时的瀑布图,可以直观地确定函数的准确行为。您可以看到每个网络呼叫仅在前一个网络呼叫完成后才会进行。所有的

queueAsyncFns waterfall graph

+0

谢谢你的解释,这更好地回答了我的问题! – vrachlin

1

如果你想等待someAsyncFunctionOnObj(OBJ1)做相同的前,但下一个物体(OBJ2,OBJ 3,...),我认为你必须链你的承诺来完成:

var promises = arrayOfObjects.map(obj => someAsyncFunctionOnObj(obj)); 
 
await promises.reduce((m, o) => m.then(() => o), Promise.resolve());

+0

你能解释第二行吗? – vrachlin

+0

它采用var promise中的所有承诺,并通过使用数组reduce减少数组使用m作为前一个承诺的内存,以便我们可以一个接一个地等待它们。然后在m上,并返回下一个承诺o,o成为m的新值,等等) – Faly

0
(async function() { 
    async function executeSequentially() { 
    const tasks = [1,2] 
    const total = [] 
    for (const fn of tasks) { 
     const res = await fetch(endpoint); 
     const res2 = await res.json(); 
     console.log(res2[0]); 
     total.push(...res2); 
    } 

    return total; 
    } 

    const res = await executeSequentially(); 
    console.log(res); 
})();