NodeJS:函数内部函数。如何让它同步?

时间:2016-12-13 19:10:46

标签: javascript node.js express async-await

假设有两个函数A和B都通过connection.query(...)方法调用mysql DB。我正在使用while循环遍历函数A中的响应。

再次,使用函数A的响应,在函数B中调用另一个DB请求并在其中循环遍历它的结果。

获取异步问题。如何解决这个问题。

307

这是实际代码:

RewriteRule ^ %1 [R=307,L,NC]

1 个答案:

答案 0 :(得分:0)

在Nodejs中, 很少 您应该进行同步调用。如果你做错了,它必然会给你的系统增压......特别是如果你有很多流量。 Nodejs是单线程的,并且完全围绕异步构建,以便正常工作。

在您的情况下,您实际上是在查询某些数据库记录并使用这些记录来填充一些JSON对象。当你完成所有这些时,你想发送一个响应,这是一个json对象数组......对吗?

我强烈建议您使用Promises。一个非常受欢迎的库可以处理这个问题:Bluebird:http://bluebirdjs.com/docs/getting-started.html

请阅读承诺,以便您真正理解他们的所作所为。简短的回答是它保持所有异步,但允许你远离回调地狱,同时使你的异步代码“读取”更多,就好像它是同步的。

最终您需要做的是宣传您的数据库查询,将数据推送到其对象然后解决。一旦解决了所有数据库调用,例如使用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)     
  });   

});