2016-12-13 65 views
-1

說有兩個函數A和B都通過connection.query(...)方法調用mysql數據庫。我使用while循環通過功能A.響應迭代NodeJS:函數內部函數。如何使它同步?

再次,從功能的響應,調用函數B另一個數據庫的請求,並通過它的結果內的另一個while循環迭代。

獲取異步問題。如何解決這個問題。

function A(){ 
    while(){ //Say, Repeat 10 times 
    function B(){ 
     while(){ 
      some_result; 
     } 
    } 
    }   
} 

這是實際的代碼:

app.get('/getmenu', function (req, res) { 

    connection.query('SELECT * from zaitoon_menutypes', function (err, rows) { 
    var output = []; 
    var i=0; 
    var j; 
    var main= rows[0].mainType; 
    var submenu=[]; 
    var items=[]; 

    //Iterate through complete menu types 
    while(i < rows.length){ 

     //Do NOT MENU TYPE switch case 
     if (main == rows[i].mainType){ 


     connection.query("SELECT * from zaitoon_menu WHERE type='type'" , function (err2, rows2, fields2){ 
     console.log('*************************'+rows2.length); 
     items = []; 
     j=0; 
     while(j < rows2.length){ 
      items.push(
      { 
      "itemCode":rows2[j].code, 
      "itemName":rows2[j].name, 
      "itemPrice":rows2[j].price 
      } 
     ); 
      j++; 
     } 
     console.log(items); 

     }); //End Connection 

     //Create Sub-menu 
     submenu.push(
      { 
      "subType" : rows[i].subType, 
      "subName" : rows[i].subName, 
      "items" : items 
      } 
     ); 

     if (i ==(rows.length-1)){ 
     output.push(
     { 
      "mainType":rows[i-1].mainType, 
      "mainName":rows[i-1].mainName, 
      "submenu": submenu 
     } 
     ); 
     } 
     } 

     //SWITCH NEXT TYPE 
     else { 
     main = rows[i].mainType; 
     output.push(
     { 
      "mainType":rows[i-1].mainType, 
      "mainName":rows[i-1].mainName, 
      "submenu": submenu 
     } 
     ); 
     var submenu=[]; 

     } 

     i++; 
    } 

    if (!err){ 
     res.setHeader('Content-Type', 'application/json'); 
     res.header("Access-Control-Allow-Origin", "*"); 
     res.status(200).send(JSON.stringify(output)) 
    } 
    else 
     res.status(500).send('Error ')  
    }) 
}) 

回答

0

在的NodeJS,很少你應該做同步調用。如果你做錯了,它肯定會軟管你的系統......特別是如果你有很多的流量。 Nodejs是單線程的,並且完全圍繞異步構建,以便正確工作。

在你的情況,你基本上查詢一些數據庫記錄,並利用這些填充一些JSON對象。在你完成所有工作的時候,你想發送一個響應,它是一個json對象的數組......對吧?

我強烈建議你在看使用的承諾。可以處理這方面的一個非常受歡迎的庫是藍鳥:http://bluebirdjs.com/docs/getting-started.html

請閱讀承諾了,所以你真正瞭解它是什麼,他們做的。簡單的答案是,它保持了一切異步,但允許你遠離回調地獄,同時也讓你的異步代碼更「讀」,就好像它是同步的。

最終你需要做的是promisify數據庫查詢,推動數據的對象,然後解決。一旦所有的數據庫調用都解決了,比如使用Promise.all(),那麼你應該發回你的res.send與對象...並且它應該充滿你需要的一切,同時避免你的異步問題。

這裏是你可以做什麼的例子。 請注意,這是未經測試的,我只是在記事本++中做到了這一點...所以如果您只是複製/粘貼,它絕對不會起作用!但它應該有希望指引你沿着正確的道路......

var Promise = require('bluebird'); 
var connection = require('mysqllibrary'); 

app.get('/getmenu', function (req, res) { 

    Promise.promisifyAll(connection); 

    connection.queryAsync('SELECT * from zaitoon_menutypes') 
    .then(function(rows){ 
     var output = []; 
     var i=0; 
     var j; 
     var main= rows[0].mainType; 
     var submenu=[]; 
     var items=[]; 
     var promises=[]; 


     //Iterate through complete menu types 
     while(i < rows.length){ 

      //Do NOT MENU TYPE switch case 
      if (main == rows[i].mainType){ 

      promises.push(connection.queryAsync("SELECT * from zaitoon_menu WHERE type='type'") 
          .then(function(rows2){ 
           console.log('*************************'+rows2.length); 
           items = []; 
           j=0; 
           while(j < rows2.length){ 
            items.push(
            { 
            "itemCode":rows2[j].code, 
            "itemName":rows2[j].name, 
            "itemPrice":rows2[j].price 
            } 
           ); 
            j++; 
           } 
           console.log(items); 
          })); 

      //Create Sub-menu 
      submenu.push(
       { 
       "subType" : rows[i].subType, 
       "subName" : rows[i].subName, 
       "items" : items 
       } 
      ); 

      if (i ==(rows.length-1)){ 
       output.push(
       { 
        "mainType":rows[i-1].mainType, 
        "mainName":rows[i-1].mainName, 
        "submenu": submenu 
       }); 
      } 
      } 
      //SWITCH NEXT TYPE 
      else { 
      main = rows[i].mainType; 
      output.push(
      { 
       "mainType":rows[i-1].mainType, 
       "mainName":rows[i-1].mainName, 
       "submenu": submenu 
      } 
      ); 
      var submenu=[]; 
      } 
      i++; 
     } 

     return Promise.all(promises).then(function() { 
      console.log("Output object has been hydrated"); 
      return output; 
     }); 

    }).then(function(output){ 
     res.setHeader('Content-Type', 'application/json'); 
     res.header("Access-Control-Allow-Origin", "*"); 
     res.status(200).send(JSON.stringify(output)) 
    }).catch(function(err){ 
     res.status(500).send('Error: ' + err)  
    }); 

});