简体   繁体   中英

Two nested async.each calls

I have the following method:

mergeAinBbyAttr: function(a, b, attr1, attr2, val, cb) {
    var result = [];
    async.each(a, function(itemA, cb1) {
        async.each(b, function(itemB, cb2) {
            if (itemA[attr1] == itemB[attr1]) {
              itemB[attr2] = val;
            }
            result.push(itemB);
            cb2(null, result);
          },
          function(e, result) {
            sails.log('[result]', result);
            cb1(e, result);
          });
      },
      function(e, result) {
        cb(e, result);
      });
  }

I basically want to compare an array of objects (A) to another array of objects (B), and return an updated array (C) with every item in B, but updates with attributes from A.

The above [result] returns undefined.

Thanks

First of all, this is all synchronous code, so you don't need async module, you just need regular looping constructs. But let's assume you need async.

Use async.map instead of async.each , for more brevity:

mergeAinBbyAttr: function(a, b, attr1, attr2, val, cb) {

    async.map(a, function(itemA, cb) {
        async.map(b, function(itemB, cb) {
            if (itemA[attr1] === itemB[attr1]) {
              itemB[attr2] = val;
            }
            cb(null, itemB);

          },cb);

      },cb);
  }

you do not need to name the cb variables different names, because they have different scopes.

If you want a flattened array at the end of this routine, I would recommend using _.flatten or _.flattenDeep from lodash or underscore.

Note that this:

function(e, result) {
   cb(e, result);
});

can just be reduced to:

cb

=================================

Doing this with synchronous methods:

    mergeByAttr: function(a, b, attr1, attr2, val) {

      return a.map(function(itemA){
          return b.map(function(itemB){
                if (itemA[attr1] === itemB[attr1]) {
                  itemB[attr2] = val;
                }
                return itemB;
           });

      });
   }

As you can see, either way, you will get nested arrays, it has nothing to do with the async module, but the nature of your code.

The more performant, but less functional way:

     mergeByAttr: function(a, b, attr1, attr2, val) {

          a.forEach(function(itemA){
              b.forEach(function(itemB){
                    if (itemA[attr1] === itemB[attr1]) {
                      itemB[attr2] = val;
                    }
                    return itemB;
               });

          });
       }

Well I watched That the answer above help you, only I want highlight one thing about your error:

[result] returns undefined.

is because according to documentation, the optional function only has 1 parameter, and you are trying to get 2 parameter: function(e, result)

http://caolan.github.io/async/docs.html#each

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM