节点JS异步响应

时间:2015-06-05 06:10:20

标签: javascript node.js mongodb asynchronous

我使用MongoDB在Node.js中编写了我的第一个应用程序,我遇到了根据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.         
        });        
    }); 
 }  

有任何建议/指示吗?

谢谢

2 个答案:

答案 0 :(得分:0)

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

例如

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这样的承诺库

答案 1 :(得分:0)

这是针对您的问题的反制解决方案。它现在应该解决你的情况。尝试阅读异步库。这对以后会非常有用。

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