2014-08-31 67 views
0

我在socket.io中抓取異步回調和變量存儲非常困難。我希望回調函數中的代碼在所有查詢完成後執行。但是,我不知道在哪裏放置callback()方法調用,以便在所有事情完成後執行。我將不勝感激任何和所有的幫助。socket.io和節點回調函數不起作用

//The code below queries a database and stores the information in a json object. 
var mysql = require('mysql') 
    var io = require('socket.io').listen(3000) 
    var db = mysql.createConnection({  
     host: '', 
     user: '', 
     password: '', 
     database: '', 
     port: 3306, 
    }) 
    db.connect(function(err){ 
     if (err) console.log(err) 
    }) 

console.log(1); 
io.sockets.on('connection', function(socket){ 
    socket.on('key', function(value){//client side has a onclick() function that emits 'key' 
     console.log(2); 
     var total = {}; 
     var personalTable = [] 
     var liwcTable = [] 
     var id = value; 

     help(total, function(total) { 
      console.log(4); 
      console.log("total = " + JSON.stringify(total)); 
      socket.emit('total', total);/emits to client 
     }); 

     function help(total, callback) { 
      console.log(3); 
      db.query('SELECT * FROM `a` WHERE `userId` =' + id) 
       .on('result', function(data){ 
        liwcTable.push(data) 
       }) 
       .on('end', function(){ 
        total["initial liwcTable"] = liwcTable; 
       }) 
      db.query('SELECT * FROM `b` WHERE `userId` =' + id) 
       .on('result', function(data){ 
        personalTable.push(data) 
       }) 
       .on('end', function(){ 
        total['personalTable'] = personalTable; 
       }) 
      callback(total)//needs to be executed after the queries are done. 
     } 
    })  
}) 

代碼在查詢有機會完成之前進入回調方法。我也不明白,當查詢回調的範圍有限時,我可以如何更新我的json對象「total」。

回答

3

您有許多解決方案可以在所有想要的操作後觸發回調。 例如,您可以創建一個在每個查詢後調用的單例,這將觸發最終的回調。

function help(total, callback) { 

    var nbEndedQueries = 0, 
     amountOfQueries = 2;//nb of linked queries 
    function singleton() { 

     //increments the nbEndedQueries variable and tests if the max is reached 
     if(++nbEndedQueries >= amountOfQueries) 
      callback(); 
    } 


    db.query(... //query calling) 
     .on('result', ...//some behaviours 
      singleton(); 
     ) 
    db.query(... //query calling) 
     .on('result', ...//some behaviours 
      singleton(); 
     ) 
    //... 

} 

另一種解決方案是使用承諾。 像Q或在ECMA6填充工具許多模塊爲您提供這個功能,它是完全以真棒

與ecm6承諾填充工具樣品

//promisification of the query method 
function query(string) { 
    return new Promise(function(resolve, reject) { 

     db.query(string) 
      .on('result', resolve) 
      //i supposed an error event exist 
      .on('error', reject); 

    }) 
} 

//and now the usage 
function help() { 

    //basic method 
    //first query calling 
    query('your query string') 
     .then(function(result) { 
      //behaviour 

      //second query calling, the result will send to the next 'then' statement 
      return query('second query'); 
     }) 
     .then(function() { 
      //behaviour 


      //at this point, all queries are finished 
      callback() ; 
     }); 
} 

//parallelized sample 

function help() { 

    //starts all queries and trigger the then if all succeeds 
    Promise.all([query('your query string'), query('second query')]) 
     .then(function(results/*array of results*/) { 
      //behaviour 

      callback(); 
     }) 
}