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

时间:2018-10-16 09:16:06

标签: express asynchronous mongoose

在我的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 个答案:

答案 0 :(得分:0)

假设您正在使用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);
        });