节点JS Promise.all和foreach [英] Node JS Promise.all and forEach
问题描述
我有这样的结构暴露异步方法的数组。异步方法调用返回的数组结构,这又暴露了更多的异步方法。我创建另一个JSON对象从这种结构获得的存储值,所以我必须小心跟踪引用的回调。
我有codeD蛮力解决方案,但我想了解一个更地道或干净的解决方案。
- 的模式应该是可重复的n级嵌套。
- 我需要使用promise.all或某些类似的技术来确定何时解决封闭例程。
- 并非所有的元素必然需要做出一个异步调用。因此,在嵌套promise.all我不能简单地进行分配,以基于索引我的JSON数组元素。不过,我确实需要使用类似嵌套的forEach promise.all,以确保所有属性分配之前已经解决封闭常规进行。
- 我使用的是蓝鸟的承诺lib目录,但这不是必需的
下面是一些偏code -
VAR jsonItems = [];items.forEach(函数(项目){ 变种jsonItem = {};
jsonItem.name = item.name;
item.getThings()。然后(功能(的东西){
//或Promise.all(allItemGetThingCalls,功能(的东西){ things.forEach(功能(的事情,指数){ jsonItems [指数] .thingName = thing.name;
如果(thing.type ==='文件'){ thing.getFile()。然后(功能(文件){//或promise.all? jsonItems [指数] .filesize = file.getSize();
这是pretty有一些简单的规则很简单:
- 当你创建一个承诺一个
然后
,返回它 - 你不返回任何承诺都不会等待外界 - 当你创建多个承诺,
。所有
他们 - 它会等待所有承诺的方式,并没有从其中任何一个错误都沉默 - 当你窝
然后
S,通常可以返回中间 - 那链通常是在1级深 - 一旦执行IO,这应该是一个承诺 - 无论它应该是一个承诺或应使用一个承诺,其信号完成
和一些技巧:
- 映射是更好地与
.MAP
做比为/推
- 如果你映射值与函数,地图
让你简洁的前preSS将动作一招一式汇总结果的概念。 - 并发比顺序执行更好,如果它是免费的 - 这是更好地并发执行的东西,恨不得
Promise.all
然后执行事一前一后。 - 每个前下一个等待
好了,让我们开始吧:
变种项= [1,2,3,4,5];
VAR FN =功能asyncMultiplyBy2(V){//样品异步操作
返回新希望(解析= GT;的setTimeout(()=>解决(V * 2),100));
};
//地图上的forEach因为它返回VAR行动= items.map(FN); //运行在所有项目的功能。//现在我们有一个承诺阵列,我们要等待它VAR的结果= Promise.all(动作); //承诺传递数组results.then(数据=> //或只。然后(的console.log)
的console.log(数据)// [2,4,6,8,10]
);//我们可以嵌套这门课程的,正如我所说,`then`链:变种RES2 = Promise.all([1,2,3,4,5] .MAP(FN))。然后(
数据=> Promise.all(Data.Map中(FN))
)。然后(功能(数据){
//后的承诺从previous返回下一`then`执行
//`then`满足,在这种情况下,这是因为聚集体许
//了`.all`
返回Promise.all(Data.Map中(FN));
})。然后(功能(数据){
//只为好措施
返回Promise.all(Data.Map中(FN));
});//现在得到的结果:res2.then(功能(数据){
的console.log(数据); // [16,32,48,64,80]
});
I have an array like structure that exposes async methods. The async method calls return array structures that in turn expose more async methods. I am creating another JSON object to store values obtained from this structure and so I need to be careful about keeping track of references in callbacks.
I have coded a brute force solution, but I would like to learn a more idiomatic or clean solution.
- The pattern should be repeatable for n levels of nesting.
- I need to use promise.all or some similar technique to determine when to resolve the enclosing routine.
- Not every element will necessarily involve making an async call. So in a nested promise.all I can't simply make assignments to my JSON array elements based on index. Nevertheless, I do need to use something like promise.all in the nested forEach to ensure that all property assignments have been made prior to resolving the enclosing routine.
- I am using the bluebird promise lib but this is not a requirement
Here is some partial code -
var jsonItems = [];
items.forEach(function(item){
var jsonItem = {};
jsonItem.name = item.name;
item.getThings().then(function(things){
// or Promise.all(allItemGetThingCalls, function(things){
things.forEach(function(thing, index){
jsonItems[index].thingName = thing.name;
if(thing.type === 'file'){
thing.getFile().then(function(file){ //or promise.all?
jsonItems[index].filesize = file.getSize();
It's pretty straightforward with some simple rules:
- Whenever you create a promise in a
then
, return it - any promise you don't return will not be waited for outside. - Whenever you create multiple promises,
.all
them - that way it waits for all the promises and no errors from any of them are silenced. - Whenever you nest
then
s, you can typically return in the middle - then chains are usually at most 1 level deep. - Whenever you perform IO, it should be with a promise - either it should be in a promise or it should use a promise to signal its completion.
And some tips:
- Mapping is better done with
.map
than withfor/push
- if you're mapping values with a function,map
lets you concisely express the notion of applying actions one by one and aggregating the result. - Concurrency is better than sequential execution if it's free - it's better to execute things concurrently and wait for them
Promise.all
then to execute things one after the other - each waiting before the next.
Ok, so let's get started:
var items = [1, 2, 3, 4, 5];
var fn = function asyncMultiplyBy2(v){ // sample async action
return new Promise(resolve => setTimeout(() => resolve(v * 2), 100));
};
// map over forEach since it returns
var actions = items.map(fn); // run the function over all items.
// we now have a promises array and we want to wait for it
var results = Promise.all(actions); // pass array of promises
results.then(data => // or just .then(console.log)
console.log(data) // [2, 4, 6, 8, 10]
);
// we can nest this of course, as I said, `then` chains:
var res2 = Promise.all([1, 2, 3, 4, 5].map(fn)).then(
data => Promise.all(data.map(fn))
).then(function(data){
// the next `then` is executed after the promise returned from the previous
// `then` fulfilled, in this case it's an aggregate promise because of
// the `.all`
return Promise.all(data.map(fn));
}).then(function(data){
// just for good measure
return Promise.all(data.map(fn));
});
// now to get the results:
res2.then(function(data){
console.log(data); // [16, 32, 48, 64, 80]
});
这篇关于节点JS Promise.all和foreach的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!