猫鼬不等待在回调中传递文档

Posted

技术标签:

【中文标题】猫鼬不等待在回调中传递文档【英文标题】:Mongoose not waiting for document to be delivered in callback 【发布时间】:2019-03-20 18:46:38 【问题描述】:

在我的 expressjs 项目中,我正在执行几个相互依赖的数据库调用。使用 pg-promise 调用 postgresql 数据库,使用 mongoose 调用 mongoDB。 一切正常,除了有时会发生,findoneandupdate() 的猫鼬回调不会等到文档被传输,这会导致下一个函数丢失数据

按预期运行代码的日志输出

5bc5a2da466f37f300d983b1 5bc5a2da466f37f300d983ba 5bc5a2da466f37f300d983b7 [ 5bc5a2da466f37f300d983b1, 5bc5a2da466f37f300d983ba, 5bc5a2da466f37f300d983b7 ]

在下一次数据库调用执行之前回调没有查询到文档时运行代码的日志输出

5bc5a2da466f37f300d983b1 5bc5a2da466f37f300d983b7 [ 5bc5a2da466f37f300d983b1, 5bc5a2da466f37f300d983b7 ] 5bc5a2da466f37f300d983ba

这是一个截取问题发生路径的代码。日志记录命令标有 ->

var questions = JSON.parse(req.headers.questions);
var client_jwt = req.headers.authorization;
var amcs_entry_list_array = [];



database.db.one('SELECT CASE WHEN EXISTS ( SELECT username FROM users WHERE $1 = ANY(tokens) ) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END', client_jwt)
.then(function (data) 

    if(data.case) 
        questions.forEach(function(question_id, idx, questionsArray) 
            var question_id = question_id.questionID; 

            database.db.multi('select * from questions where id = $1;select * from choices where question_id = $1', question_id)
            .then(function (data) 

                mongoose_models_amcs_entry.amcs_entry.findOneAndUpdate(
                    amcs_request: question_id: question_id,request_jwt: client_jwt,          
                    amcs_request: question_id: question_id,request_jwt: client_jwt,amcs_response: question_data: data[0], choices_data: data[1], 
                    upsert:true,new:true, 
                    function(err, doc)
                    if (err) return handleError(err);
                    amcs_entry_list_array.push(doc._id);
                 ->   console.log(doc.id);
                    if (idx === questionsArray.length - 1) //if last response arrived
                     ->   console.log(amcs_entry_list_array);
                        mongoose_models_amcs_entry_list.amcs_entry_list.findOneAndUpdate(
                            amcs_entry_list: document_ids: amcs_entry_list_array,          
                            amcs_entry_list: document_ids: amcs_entry_list_array,         
                            upsert:true,new:true, 
                            function(err, doc)
                            if (err) return handleError(err);
                            res.send("http://localhost:8080/entry/"+doc._id);
                        );

                    
                );


            )
            .catch(function (error) 
                console.log("ERROR:", error);
            );


        );

    

在标记的 console.log() 命令之后执行回调之前,如何强制回调等待“doc”交付?

【问题讨论】:

【参考方案1】:

假设您使用的是 es2016。这样,您的代码将等待结果并且不会跳转到下一条指令。你可以访问这里了解更多https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Statements/async_function

作为参考,您的代码将如下所示。

database.db.one('SELECT CASE WHEN EXISTS ( SELECT username FROM users WHERE $1 = ANY(tokens) ) THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END', client_jwt)
.then(function (data) 

if(data.case) 
        questions.forEach(async function(question_id, idx, questionsArray) 
         var question_id = question_id.questionID; 
     var data = await database.db.multi('select * from questions where id = $1;select * from choices where question_id = $1', question_id)

    var output = await mongoose_models_amcs_entry.amcs_entry.findOneAndUpdate(
                                amcs_request: question_id: question_id,request_jwt: client_jwt,          
                                amcs_request: question_id: question_id,request_jwt: client_jwt,amcs_response: question_data: data[0], choices_data: data[1], 
                                upsert:true,new:true)
     if (!optput._id) return handleError(err);
                amcs_entry_list_array.push(doc._id);
     console.log(doc.id);
     if (idx === questionsArray.length - 1) //if last response arrived
           console.log(amcs_entry_list_array);
 var out1 = await mongoose_models_amcs_entry_list.amcs_entry_list.findOneAndUpdate(
                                            amcs_entry_list: document_ids: amcs_entry_list_array,          
                                            amcs_entry_list: document_ids: amcs_entry_list_array,         
                                            upsert:true,new:true) 
    if (!out1._id) return handleError(err);
    res.send("http://localhost:8080/entry/"+doc._id);
                    
                    );
        
        )
        .catch(function (error) 
                console.log("ERROR:", error);
        );

【讨论】:

不幸的是,这没有帮助。当我以您提供的方式更改代码并使周围的功能“异步”时,我根本没有得到猫鼬的任何响应。谢谢你的回答 @I.嘘不要忘记“等待”,你现在有什么错误吗? @I.Shm 我错过了猫鼬查询之前的等待,请添加(再次查看答案,我只是编辑) 似乎您删除了 .then( function (data) ,这是故意的吗?当我更改代码时它不起作用:( @I.Shm 是的,当我们使用 await 时,我们不需要 .then(function(data)) 因为var data = await query()query().then() 相同

以上是关于猫鼬不等待在回调中传递文档的主要内容,如果未能解决你的问题,请参考以下文章

将回调代码改进为异步等待猫鼬

在猫鼬中执行 CRUD 操作时异步/等待

等待解决多个回调

为啥猫鼬不更新?

如何等待传递给 Flask-SocketIO 的 emit() 的回调?

猫鼬不发送更新的结果[重复]