节点JS Promise.all和foreach [英] Node JS Promise.all and forEach

查看:1433
本文介绍了节点JS Promise.all和foreach的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这样的结构暴露异步方法的数组。异步方法调用返回的数组结构,这又暴露了更多的异步方法。我创建另一个JSON对象从这种结构获得的存储值,所以我必须小心跟踪引用的回调。

我有codeD蛮力解决方案,但我想了解一个更地道或干净的解决方案。


  1. 的模式应该是可重复的n级嵌套。

  2. 我需要使用promise.all或某些类似的技术来确定何时解决封闭例程。

  3. 并非所有的元素必然需要做出一个异步调用。因此,在嵌套promise.all我不能简单地进行分配,以基于索引我的J​​SON数组元素。不过,我确实需要使用类似嵌套的forEach promise.all,以确保所有属性分配之前已经解决封闭常规进行。

  4. 我使用的是蓝鸟的承诺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.

  1. The pattern should be repeatable for n levels of nesting.
  2. I need to use promise.all or some similar technique to determine when to resolve the enclosing routine.
  3. 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.
  4. 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 thens, 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 with for/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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆