异步 Mongoose 调用

Posted

技术标签:

【中文标题】异步 Mongoose 调用【英文标题】:Asynchronous Mongoose Calls 【发布时间】:2017-06-21 04:54:05 【问题描述】:

我有一个match 函数,可以将两个交换赌注配对或部分配对。起初我编写了一个简洁的函数,但它是同步的(使用 for 循环),现在我无法使用嵌套回调和 async 包将其转换为异步代码。到目前为止,我将粘贴到我的同步和异步函数下方。目前,我在异步代码中遇到错误,因为Cannot read property '_id' of undefined_id 是从存储在results 中的查询中提取的。

异步函数

match : function()
    var results = Bet.find("paired" : false, _id:1, bet:1, market:1, odds:1, student:1, to_match:1, stake:1)
    .sort(createdAt : 1);
    async.forEach(results, function(doc, callback)
        var result = doc[0];
        var id = result._id;
        var stake = result.stake;
        var odds = result.odds;
        var market = result.market;
        var student = result.student;
        var side = result.bet;
        var to_match = result.to_match;
        var opp_results = Bet.find("student":student, "market":market, "paired":false, "settled":false, 
            "bet": $ne : side, "_id" : $ne : id);
        async.forEach(opp_results, function(opp_doc, callback2)
            var temp_to_match = to_match;
            var array = opp_doc[0];
            var opp_id = array._id;
            console.log("Comparing " + id + " with " + opp_id);
            var opp_paired = array.paired;
            var opp_to_match = array.to_match;
            var opp_settled = array.settled;
            if(temp_to_match <= opp_to_match)
                temp_to_match -= opp_to_match;
                opp_to_match -= temp_to_match;
                if(temp_to_match <= 0)
                    paired = true;

                
                if(opp_to_match <= 0)
                    opp_paired = true;
                
            
        , callback);
    , function(err)
        console.log("done");
    );

同步功能

sync_match : function()
    Bet.find("paired" : false, _id:1, bet:1, market:1, odds:1, student:1, to_match:1, stake:1)
    .sort(createdAt : 1)
        .then(function(doc)
            for(var j = 0; j < doc.length; j++)
            var result = doc[j];
            var id = result._id;
            var stake = result.stake;
            var odds = result.odds;
            var market = result.market;
            var student = result.student;
            var side = result.bet;
            var to_match = result.to_match;
            Bet.find("student":student, "market":market, "paired":false, "settled":false, 
                "bet": $ne : side, "_id" : $ne : id).then(function(results)
                for(var i = 0; i < results.length; i++)
                    var temp_to_match = to_match;
                    var array = results[i];
                    var opp_id = array._id;
                    console.log("Comparing " + id + " with " + opp_id);
                    var opp_paired = array.paired;
                    var opp_to_match = array.to_match;
                    var opp_settled = array.settled;
                    if(temp_to_match <= opp_to_match)
                        temp_to_match -= opp_to_match;
                        opp_to_match -= temp_to_match;
                        if(temp_to_match <= 0)
                            paired = true;

                        
                        if(opp_to_match <= 0)
                            opp_paired = true;
                        
                    console.log("we made it this far);
                    
                

            );

    );

【问题讨论】:

Bet.find 是异步的,所以你不能像这样使用它var results = Bet.find(...) 最简单的方法是添加exec -> Bet.find(...).sort(...).exec(function(err, results) async.forEach(results, ...)); 【参考方案1】:

(更新:此解决方案有一个小错误。由于某种原因,当一个字段配对时,它应该停止,但它会继续配对和配对..)

根据 Molda 的建议,我设法获得了一个可行的异步解决方案:

match : function()
    Bet.find("paired" : false, _id:1, bet:1, market:1, odds:1, student:1, to_match:1, stake:1)
    .sort(createdAt : 1).exec(function(err, results)
    async.forEach(results, function(doc, callback)
        var id = doc._id;
        var stake = doc.stake;
        var odds = doc.odds;
        var market = doc.market;
        var student = doc.student;
        var side = doc.bet;
        var to_match = doc.to_match;
        Bet.find("student":student, "market":market, "paired":false, "settled":false, 
        "bet": $ne : side, "_id" : $ne : id).exec(function(errs, res)
        async.forEach(res, function(opp_doc, callback2)
            var temp_to_match = to_match;
            var opp_id = opp_doc._id;
            var opp_student = opp_doc.student;
            var opp_paired = opp_doc.paired;
            var opp_to_match = opp_doc.to_match;
            var opp_settled = opp_doc.settled;
            if(temp_to_match <= opp_to_match)
                var update_to_match = temp_to_match - opp_to_match;
                var update_opp_to_match = opp_to_match - temp_to_match
                if(update_to_match <= 0)
                    paired = true;
                    update_to_match = 0;

                
                if(update_opp_to_match <= 0)
                    opp_paired = true;
                    update_opp_to_match = 0;
                
                Bet.update("_id" : id, 
                    $set : 'to_match': update_to_match,'paired' : paired
                    ,new : true, multi: true).exec(function(err)
                        if(err)
                            throw err;
                    );
                Bet.update("_id" : opp_id, 
                    $set : 'to_match': update_opp_to_match, 'paired' : opp_paired
                    ,new : true, multi:true).exec(function(err)
                        if(err)
                            throw err;
                    );
            
        , function(err)
            if(err)
                throw err;
            
            callback();
        ));
    , function(err)
        console.log("done");
    ));

【讨论】:

以上是关于异步 Mongoose 调用的主要内容,如果未能解决你的问题,请参考以下文章

如何确保在从 Mongoose 中的函数返回之前执行异步调用?

Mongoose 异步多次保存冲突

then 语句中的异步 Mongoose 回调

Mongoose与bluebird结合使用实例

Node.js/Mongoose 等待异步 For 循环

如何在 for 循环中运行 mongoose 方法,因为 mongoose 函数是异步的