如何使用async forEach一个接一个地迭代两个数组

时间:2018-10-11 14:37:12

标签: node.js async.js

我有两个数组。我想使用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被调用。为什么不第一个被执行。 我的代码有什么错误吗?有人可以解决这个问题吗?

1 个答案:

答案 0 :(得分:0)

这种简单的技术怎么样:

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。这样的事情应该做到:

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数组,但我认为现在就足够了:)。希望对您有所帮助。