最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Async - parallel() with functions dynamic array - Stack Overflow

programmeradmin0浏览0评论

I am using the excellent caolan "async" module for nodejs:

I have this code:

exports.manageComments = function(req, res) {
    var toDeleteIds = [];
    var deleteFunctions = [];
    if (req.body.doDelete) {
        toDeleteIds = req.body.doDelete;
    }
    var i;
    for ( i = 0; i < toDeleteIds.length; i++ ) {
        var deleteFunction = function(callback) {
            var id = toDeleteIds[i];
            console.log(id);
            Comment.findOne({_id:id}, function(err, found) {            
                if (!err) found.remove(callback);
            });
        }
        deleteFunctions.push(deleteFunction);
    }
    async.parallel(
        deleteFunctions,
        function(err,results) {
            exportsments(req, res); //render a view
        }
    );
};

My array contains two elements but console.log() keeps telling me "undefined".

What am I missing?

I am using the excellent caolan "async" module for nodejs:

I have this code:

exports.manageComments = function(req, res) {
    var toDeleteIds = [];
    var deleteFunctions = [];
    if (req.body.doDelete) {
        toDeleteIds = req.body.doDelete;
    }
    var i;
    for ( i = 0; i < toDeleteIds.length; i++ ) {
        var deleteFunction = function(callback) {
            var id = toDeleteIds[i];
            console.log(id);
            Comment.findOne({_id:id}, function(err, found) {            
                if (!err) found.remove(callback);
            });
        }
        deleteFunctions.push(deleteFunction);
    }
    async.parallel(
        deleteFunctions,
        function(err,results) {
            exports.comments(req, res); //render a view
        }
    );
};

My array contains two elements but console.log() keeps telling me "undefined".

What am I missing?

Share Improve this question edited Aug 11, 2015 at 20:56 Bergi 665k161 gold badges1k silver badges1.5k bronze badges asked Sep 18, 2012 at 7:40 Fabio B.Fabio B. 9,40028 gold badges110 silver badges183 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 12

Your problem is with:

    var deleteFunction = function(callback) {
        var id = toDeleteIds[i];

because at the time each callback function is executed, i will have the same value as toDeleteIds.length. A closure doesn't "trap" the value that an outer variable had at the time it was created; it "traps" a reference to whatever value the outer variable has at the time it's executed (which in this case won't be until well after your for loop has finished.

In order to "trap" the value of i at the time you create your callback function, you need to make i a parameter of a function that you call to create your callback function. You need something like

    var deleteFunction = makeDeleteFunction(i, callback);

And then create a separate function outside the callback:

function makeDeleteFunction(i, callback) {
    return function(callback) {
        var id = toDeleteIds[i];
        console.log(id);
        Comment.findOne({_id:id}, function(err, found){            
            if (!err) found.remove(callback);
        });
     };
}

ebohlman has correctly identified the problem. However I still think creating an array of closures is hugely inefficient and unnecessary. Here's shorter, easier code to achieve the same with a single function:

exports.manageComments = function(req, res) {
    var toDeleteIds = [];
    if (req.body.doDelete) {
        toDeleteIds = req.body.doDelete;
    }

    var deleteFunction = function(id, callback) {
        console.log(id);
        Comment.findOne({_id:id}, function(err, found) {            
            if (!err) found.remove(callback);
        });
    }

    async.forEach(toDeleteIds, deleteFunction, function(err,results) {
        exports.comments(req, res); //render a view
    });
};

Looking at this another way, if you don't need to fire the Mongoose remove middleware on each Comment doc being removed, you can remove all identified comments in one go:

Comment.remove({_id: {$in: toDeleteIds}}, function(err, numRemoved) {
    exports.comments(req, res); //render a view        
}
发布评论

评论列表(0)

  1. 暂无评论