如何跳过"async.forEachOf"在Node.js中循环迭代

How to Skip a "async.forEachOf" loop iteration in Node.js

本文关键字:quot js 循环 迭代 Node forEachOf 何跳过 async      更新时间:2023-09-26

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

在您的第一个解决方案中,当索引匹配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')
})

在第二种解决方案中,如果index匹配1,则不带参数调用callback,并跳过带空参数调用callback。还是没有冲出瀑布

用瀑布法解决你的问题,你有两个选择。

  1. 用一个error参数调用waterfall的callback方法,它会跳出waterfall,然后在waterfall的回调中处理这个错误。

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