-->

how to iterate two arrays one after other using as

2019-08-28 12:49发布

问题:

I have two arrays. I would like to iterate the arrays using async.foreach. But when I do so, only the second array is getting executed.How to execute both. Below is my code:

var _sizesArray1 = [_2000px, _1400px]
var _sizesArray2 = [_800px, _400px, _200px, _100px]
 
 async.forEachOf(_sizesArray1, function(value, key, callback) {
        async.waterfall([
        function download(next){
        //code
        },
        function convert(response, next) {
        //code
        },
        function process(response, next) {
        gm(response).command('convert')
            .resize(_sizesArray[key].width,_sizesArray[key].width)
            .gravity('Center')
            .extent(_sizesArray[key].width,_sizesArray[key].width)
            .quality('20')
            .toBuffer(
                    'JPG', function(err,
                        buffer) {
                        if (err) {
                            
                            next(err);
                        } else {
                            console.timeEnd(
                                "processImage array1"
                            );
                            next(null,
                                buffer,
                                key);
                            
                        }
                    });
        }
        });
        
  async.forEachOf(_sizesArray2, function(value, key, callback) {
        async.waterfall([
        function download1(next){
        //code
        },
        function convert2(response, next) {
        //code
        },
        function process3(response, next) {
        //code
        }
        });

In my code, only array2 is getting invoked.Why don't first one get executed. Is there any mistake in my code. Can somebody help resolve this.

回答1:

How about this simple technique:

var allSizes = _sizesArray1.concat(_sizesArray2);
async.foreach(allSizes, function(value, key, next) {
   // do whatever you like with each item in the concatenated arrays

   // once you are done move to the next item
   next()
})

Updated based on comments

Version 1, based on callbacks (welcome callback hell):

function asyncIterate(array, onEach, onDone) {
  async.forEach(array, (val, index, onNext) => {
    onEach(val, key, function onDecoratedNext() {
      // tell the async.forEach it's ready for the next item
      onNext();

      // but if it got to the end, 
      //  then mark the completion of the whole iteration
      if (index === array.length) {
        onDone();
      }
    });
  });

}

and implement it like:

function doAsyncStuffWithEachItem(val, index, cb) {
  // do async stuff with each item

  // make sure to mark the completion of the async operation
  cb();
}

asyncIterate(
  _sizesArray1, 
  doAsyncStuffWithEachItem,
  function onDone() {
    // once the 1st iteration finished, time to move to the 2nd array
    asyncIterate(
      _sizesArray2,
      doAsyncStuffWithEachItem,
      function onDone2() {
        // great we are done

        // What if we have _sizesArray3, 4, 5 ... ?
        // Well, we can continue to nest more callback here
        //  but in that way we'll soon end up with callback hell 
        //  and that's a big NoNo
      }      
    )
  }
);

Version 2, based on Promises:

To avoid callback hell, luckily we can use Promises. Something like this should do it:

const promisifiedAsyncIterate = (array, onEach) => 
  new Promise((resolve) => {
    asyncIterate(array, onEach, resolve);
  });

and use it like:

promisifiedAsyncIterate(_sizeArray1, doAsyncStuffWithEachItem)
  .then(() => promisifiedAsyncIterate(_sizeArray2, doAsyncStuffWithEachItem))
  .then(() => promisifiedAsyncIterate(_sizeArray3, doAsyncStuffWithEachItem))
  .then(() => promisifiedAsyncIterate(_sizeArray4, doAsyncStuffWithEachItem))

It could be abstracted and cleaned up even more, or even made completely dynamic – say you have an array of sizeArrays that you pass in to your function, but I think this is enough for now :). Hope it helps.