3

私はnodejs用の優れたcaolan「async」モジュールを使用しています:

私はこのコードを持っています:

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

私の配列には 2 つの要素が含まれていますが、console.log() は「未定義」と言い続けます。

私は何が欠けていますか?

4

3 に答える 3

11

あなたの問題は次のとおりです。

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

各コールバック関数が実行される時点で、iは と同じ値になるためtoDeleteIds.lengthです。クロージャーは、作成時に外部変数が持っていた値を「トラップ」しません。実行時に外部変数が持つ値への参照を「トラップ」します(この場合、forループが終了するまではトラップされません。

iコールバック関数の作成時にの値を「トラップ」するには、コールバック関数iを作成するために呼び出す関数のパラメーターを作成する必要があります。次のようなものが必要です

    var deleteFunction = makeDeleteFunction(i, 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);
        });
     };
}
于 2012-09-18T10:02:08.553 に答える
3

ebohlman は問題を正しく特定しました。ただし、クロージャーの配列を作成することは非常に非効率的で不必要だと思います。単一の関数で同じことを達成するための短くて簡単なコードを次に示します。

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
    });
};
于 2012-09-18T22:19:22.927 に答える
2

remove別の見方をすると、ドキュメントを削除するたびに Mongoose ミドルウェアを起動する必要がない場合は、Comment特定されたすべてのコメントを一度に削除できます。

Comment.remove({_id: {$in: toDeleteIds}}, function(err, numRemoved) {
    exports.comments(req, res); //render a view        
}
于 2012-09-18T22:36:55.310 に答える