【问题标题】:How to Skip a "async.forEachOf" loop iteration in Node.js如何在 Node.js 中跳过“async.forEachOf”循环迭代
【发布时间】:2015-10-27 05:59:45
【问题描述】:

async.waterfall 嵌套在 async.forEachOfLimit 循环中,如下面的代码所示。

问题:当代码在async.waterfall 中执行一个步骤时,如何跳过async.forEachLimit 的迭代?换句话说,突破async.waterfall 并回到async.forEachLimit。我已经在代码中注释了应该进行此检查的位置

当前代码报错Callback was already called.

另外,如果我想突破async.waterfall 时使用return callback() 代替cb(),则不会发生错误,但不会被跳过。

var async = require('async')
var users = ['a','b','c']

async.forEachOfLimit(users, 1, function(user, index, cb) {

    console.log(index + ': ' + user)

    async.waterfall([
        function(callback) {
            callback(null);
        },
        function(callback) {
            // Skip async.forEAchOfLimit iteration when index == 1
            if(index == 1)
                cb()

            callback(null);
        }
    ], function (err, result) {
        console.log(index + ": done")
        cb()
    });

}, function() {
    console.log('ALL done')
})

错误

0: a
0: done
1: b
2: c
1: done

/Users/x/test/node_modules/async/lib/async.js:43
            if (fn === null) throw new Error("Callback was already called.");
                                   ^
Error: Callback was already called.

期望的输出

0: a
0: done
1: b
2: c
2: done
ALL done

使用return callback()

var async = require('async')
var users = ['a','b','c']

async.forEachOfLimit(users, 1, function(user, index, cb) {

    console.log(index + ': ' + user)

    async.waterfall([
        function(callback) {
            callback(null);
        },
        function(callback) {
            // Skip async.forEAchOfLimit iteration when index == 1
            if(index == 1)
                return callback()

            callback(null);
        }
    ], function (err, result) {
        console.log(index + ": done")
        cb()
    });

}, function() {
    console.log('ALL done')
})

输出

不会爆发...

0: a
0: done
1: b
1: done
2: c
2: done
ALL done

【问题讨论】:

  • 你的意思是,就像一个正常循环中的break

标签: javascript node.js asynchronous


【解决方案1】:

在您的第一个解决方案中,当索引匹配 1 时,cb 被调用两次,这就是为什么您不断收到 Callback was already called 错误的原因。尽管您调用 forEachOfLimit 回调 cb,但您的代码不会停止执行并调用回调。在回调函数cb 中再执行一次。

var async = require('async')
var users = ['a','b','c']

async.forEachOfLimit(users, 1, function(user, index, cb) {

    console.log(index + ': ' + user)

    async.waterfall([
        function(callback) {
            callback(null);
        },
        function(callback) {
            // Skip async.forEAchOfLimit iteration when index == 1
            if(index == 1)
                cb() // First callback call

            callback(null);
        }
    ], function (err, result) {
        console.log(index + ": done")
        cb() // Second callback call
    });

}, function() {
    console.log('ALL done')
})

在第二种解决方案中,如果索引匹配 1,它会调用不带参数的回调,并跳过带空参数的回调。仍然没有跳出瀑布。

要使用瀑布解决您的问题,您有两种选择。

  1. 使用错误参数调用瀑布的方法回调,它会跳出瀑布并在瀑布的回调中处理此错误。

    var async = require('async')
    var users = ['a','b','c']
    
    async.forEachOfLimit(users, 1, function(user, index, cb) {
    
        console.log(index + ': ' + user)
    
        async.waterfall([
            function(callback) {
                callback(null);
            },
            function(callback) {
                // Skip async.forEAchOfLimit iteration when index == 1
                if(index == 1)
                    return callback(new Error('Index equals 1'));
    
                callback(null);
            }
        ], function (err, result) {
            console.log(index + ": done")
    
            if(err.message == 'Index equals 1') {
                err = null; // If you want to continue executing forEachOfLimit no error must be passed to cb
            }
    
            cb(err, result);
        });
    
    }, function() {
        console.log('ALL done')
    });
    
  2. 在每个瀑布式方法的开头跳过其余代码并立即调用回调(这是您在第二次尝试中所做的)

    var async = require('async')
    var users = ['a','b','c']
    
    async.forEachOfLimit(users, 1, function(user, index, cb) {
    
        console.log(index + ': ' + user)
    
        async.waterfall([
            function(callback) {
                callback(null);
            },
            function(callback) {
                // Skip execution of the rest of waterfall method immediately
                if(index == 1)
                    return callback()
    
                // Some additional code here
    
                callback(null);
            }
        ], function (err, result) {
            console.log(index + ": done")
            cb()
        });
    
    }, function() {
        console.log('ALL done')
    })
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-29
    • 2021-11-15
    • 2019-05-17
    • 1970-01-01
    相关资源
    最近更新 更多