【问题标题】:Node JS Async Response节点 JS 异步响应
【发布时间】:2015-08-19 23:41:45
【问题描述】:

我在 Node.js 中使用 MongoDB 编写了我的第一个应用程序,我遇到了需要根据 IF/ELSE 条件有 2 个 db.collection.update 语句的情况。 我正在尝试返回 resJSON JS 对象中的操作详细信息,但似乎回调在 db.collection.update 语句完成之前执行,并且 resJSON 的默认值每次都会得到响应。

详细代码:

var url = require('url');
var fs = require('fs');
var async = require('async');
var passwordGen = require('../../lib/passwordGen');

var http = require("http");
var server = http.createServer();
server.on('request', request);
server.listen(8080,'127.0.0.1');
function request(request, response) {
    var userData = '';

    request.on('data', function(data) 
    {
        userData += data;
    });
    request.on('end', function() 
    {
      async.auto({                           
        allProcess: function(callback){                                 
            var resJSON  = {'inserted':0,'disabled':0,'error':''};        
            var jsonData = JSON.parse(userData);   
           if(jsonData.length > 0){

            var MongoClient = require('mongodb').MongoClient;

            MongoClient.connect("mongodb://localhost:27017/test_db", function(err,db){
                  if(err) { return console.dir(err); }

                   var collection = db.collection('users');
                   var arrDisableRec = [];  

                   for(i=0;i<jsonData.length;i++){
                      var action = jsonData[i]['action'].toLowerCase();

                      if(action == 'disable'){           
                          arrDisableRec.push(jsonData[i]['email']);                                            
                      }else{
                          var date = new Date();
                          var obj = { 
                                      'createdISO':date,
                                      'created':date,
                                      'updated':date,
                                      'updatedISO':date,
                                      'email':jsonData[i]['email'],
                                      'firstName':jsonData[i]['firstname'],
                                      'lastName':jsonData[i]['lastname'],
                                      'password':passwordGen.getPassword(),
                                      'enabled':true,
                                      'active':true,
                                      'downloaded':true,
                                      'defaultServings':2,
                                      'name':''
                                    };
                                 collection.update(
                                     {'email':jsonData[i]['email']},
                                     {$setOnInsert:obj},
                                     {upsert: true},  
                                     function(err,numberAffected,rawResponse) { 
                                        if(typeof numberAffected.result.upserted != 'undefined'){
                                          resJSON['inserted'] = resJSON['inserted'] + numberAffected.result.upserted.length; 
                                        }   

                                        if(typeof numberAffected.result.nModified != 'undefined'){                                                                    
                                          resJSON['disabled'] = resJSON['disabled'] + parseInt(numberAffected.result.nModified);
                                        }                                                 
                                        if(typeof numberAffected.result.writeError != 'undefined'){                   
                                          resJSON['error'] ='Error Code:'+(numberAffected.result.writeError.code)+', '+numberAffected.result.writeError.errmsg;                                                                                
                                        }
                                        console.log(resJSON); //shows correct values           
                                    }
                          );
                      }     
                      if(arrDisableRec.length > 0){
                          collection.update(
                                     {'email':{$in:arrDisableRec}},
                                     {$set:{'enabled':false}},
                                     {multi:true},
                                     function(err,numberAffected,rawResponse) {  
                                      if(typeof numberAffected.result.upserted != 'undefined'){
                                        resJSON['inserted'] = resJSON['inserted'] + numberAffected.result.upserted.length; 
                                      }   

                                      if(typeof numberAffected.result.nModified != 'undefined'){                                                                    
                                        resJSON['disabled'] = resJSON['disabled'] + parseInt(numberAffected.result.nModified);
                                      }                                                 
                                      if(typeof numberAffected.result.writeError != 'undefined'){                   
                                        resJSON['error'] ='Error Code:'+(numberAffected.result.writeError.code)+', '+numberAffected.result.writeError.errmsg;                                                                                
                                      }     

                                        console.log(resJSON);   //shows correct values    
                                    }
                             );
                        }
                   }          

               });
            } 
            callback(resJSON);
        }         
        },function(resJSON){
            response.writeHead(200,{
                  'Content-Type': 'text/json'
                });                          
            response.end(JSON.stringify(resJSON));    //replies back with default resJSON only.         
        });        
    }); 
 }  

请问有什么建议/方向吗?

谢谢

【问题讨论】:

  • 你做错了。您将异步任务放在 for 循环中,该循环将在您从所有项目的更新操作返回之前完成其所有迭代。我推荐你 async,js 库。学习和使用 async.each 函数。它应该可以解决您的回调被调用的第一个问题。
  • 根据 StackOverflow 指南,应将与问题相关的代码粘贴到问题中,而不仅仅是在外部链接中提供。
  • @jfriend00 太长粘贴在这里
  • @SumanLama 你的意思是不能以这种方式收集信息?我将不得不重新调整代码?
  • 关于代码的问题必须在您的问题中包含相关代码。您链接到的代码可以提取到相关部分并粘贴到此处。这些是 StackOverflow 指南。链接习惯于随着时间的推移变得功能失调或发生变化,然后这个问题作为知识库变得毫无意义,这是 StackOverflow 价值的重要组成部分。

标签: javascript node.js mongodb asynchronous


【解决方案1】:

你必须在回调链的末尾调用回调。

例如

console.log(resJSON); //shows correct values
callback(null, resJSON);

您必须确保每个回调链端点都调用回调。要处理 for 循环,您必须有一种机制来连接在 for 循环内完成的所有异步调用的所有端点。

例如

if(err) {
   return callback(err);
}

请注意,我使用了 function callback(err, res) 标准节点原型,而不是您的 function callback(res)

更好的是,使用像 async 这样的异步流库或像 bluebird 这样的 promise 库

【讨论】:

  • 我需要在更新语句中有一个回调链吗?对不起..我在这里有点困惑..如果可能的话,你能帮忙举个例子吗?
【解决方案2】:

这是针对您的问题的反解决方案。它现在应该可以解决您的问题。尝试阅读异步库。以后会很有用的。

    var counter = 0;
    function commoncallback(err,numberAffected,rawResponse) { 
        if(typeof numberAffected.result.upserted != 'undefined'){
            resJSON['inserted'] = resJSON['inserted'] + numberAffected.result.upserted.length; 
        }
        if(typeof numberAffected.result.nModified != 'undefined'){                                                                    
            resJSON['disabled'] = resJSON['disabled'] + parseInt(numberAffected.result.nModified);
        }                                                 
        if(typeof numberAffected.result.writeError != 'undefined'){                   
            resJSON['error'] ='Error Code:'+(numberAffected.result.writeError.code)+', '+numberAffected.result.writeError.errmsg;                                                                                
        }
        console.log(resJSON); //shows correct values   
        counter --;
        if(counter == 0) callback(resJSON); //call your main call back here
    }
    for (i=0; i<jsonData.length; i++) {
        if(firstCase) {
            counter ++;
            collection.update({'email':{$in:arrDisableRec}},
                              {$set:{'enabled':false}},
                              {multi:true},commoncallback);
        } else {
              //another update action
              counter++;
        }
    }

【讨论】:

    猜你喜欢
    • 2015-07-25
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2018-09-03
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多