【问题标题】:how to iterate two arrays one after other using async forEach如何使用 async forEach 依次迭代两个数组
【发布时间】:2018-10-12 02:47:43
【问题描述】:

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

【问题讨论】:

  • 你是在两个循环中都使用 _sizesArray2 还是复制错误?
  • 我在这里错误地更新了代码,我正在使用 _sizesArray1 & _sizesArray2。
  • 通过更改两个数组中的函数名称,我确实在一定程度上实现了这一点。但是应用程序有时会处理两个数组中的所有维度,但有时它只是随机选择几个维度。这是由于缓冲区限制。遍历第一个数组后如何清理缓冲区。

标签: node.js async.js


【解决方案1】:

这个简单的技术怎么样:

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

根据 cmets 更新

版本 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 数组,你可以传递给你的函数,但我认为现在这已经足够了 :)。希望对您有所帮助。

【讨论】:

  • 我的问题最初是为了克服 aws lambda 中的缓冲区限制错误。如果我在处理大文件时将所有维度都放在单个数组中,则它超出了内存限制。因此我将它分成数组并一个接一个地迭代它们。所以现在我需要在处理第一个数组后清除/处理缓冲区
  • 有趣。嗯,那么我看到这个工作的唯一方法是将第二个数组的迭代推迟到第一个数组完成。让我想一个干净的解决方案,我会尽快更新答案。
  • @merla 查看更新版本,如果您需要任何说明或有任何问题,请告诉我。
猜你喜欢
  • 1970-01-01
  • 2015-06-06
  • 1970-01-01
  • 2012-08-10
  • 2022-06-26
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
相关资源
最近更新 更多