首页 > 解决方案 > 如何使用 async forEach 依次迭代两个数组

问题描述

我有两个数组。我想使用 async.foreach 迭代数组。但是当我这样做时,只有第二个数组被执行。如何执行两者。下面是我的代码:

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
        }
        });

在我的代码中,只有 array2 被调用。为什么不执行第一个。我的代码中是否有任何错误。有人可以帮助解决这个问题。

标签: node.jsasync.js

解决方案


这个简单的技术怎么样:

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()
})

根据评论更新

版本 1,基于回调(欢迎回调地狱):

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();
      }
    });
  });

}

并像这样实现它:

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
      }      
    )
  }
);

版本 2,基于 Promises:

为了避免回调地狱,幸运的是我们可以使用 Promises。这样的事情应该这样做:

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

并像这样使用它:

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

它可以被进一步抽象和清理,甚至可以完全动态化——比如你有一个 sizeArrays 数组,你可以传递给你的函数,但我认为现在这已经足够了 :)。希望能帮助到你。


推荐阅读