节点.js处理异步

Node.js Dealing with Async

本文关键字:异步 处理 js 节点      更新时间:2023-09-26

我试图了解node.js的异步性质。我有一条快速路线,我知道它下面不会提供我需要的数据。从本质上讲,第一个 mysql 查询按预期 100% 工作,并且在 res.json 中返回的 json 数据是正确的。然而,在第一个mysql函数中,我调用另一个函数"getOrderLines()",它总是返回'{"Item":[]}'而不是我期望的数据。

我知道这是因为节点的异步性质而发生这种情况,但是我似乎无法解决这个问题,我已经研究了承诺并编写了一些基本承诺,但无法让它适用于以下内容。

任何帮助将不胜感激。

router.route('/salesOrders')
    .get(function (req, res) {
            mysql.query("QUERY", function (err, sql1) {
                    for (i = 0; i < sql1.length; i++) {
                        json.Company.SalesOrders.SalesOrder[i] = {
                            "Id": sql1[i].Id,
                            "AccountReference": sql1[i].AccountReference,
                            "SalesOrderDate": sql1[i].SalesOrderDate,
                            "SalesOrderAddress": [{
                                "Forename": sql1[i].billFirstname,
                                "Lastname": sql1[i].billLastName,
                                "Address": sql1[i].billAddress1
                            }],
                            "SalesOrderItems": {}
                        };
                        json.Company.SalesOrders.SalesOrder[i].SalesOrderItems = getOrderLines(sql1[i].Id);
                    } // End first For loop.
                    res.json(json);
                };
            };
            getOrderLines = function (orderId) {
                var orderLineJson = {
                    "Item": []
                };
                mysql.query('QUERY', function (err, sql2) {
                    for (j = 0; j < sql2.length; j++) {
                        orderLineJson.Item[j] = {
                            "SKU": sql2[j].name,
                            "QtyOrdered": sql2[j].quantity,
                            "UnitPrice": sql2[j].price
                        };
                    }
                });
                return orderLineJson;
            };

处理异步操作时不能使用 return。我建议学习和实践承诺。起初它们有点难以理解,但一旦点击,我想你会更喜欢它们继续通过,你可以从那里开始。

现在,您需要学习使用回调。承诺仍然使用回调。将回调传递给异步函数,并在异步操作完成后调用它:

function getOrderLines(orderId, cb) {
    mysql.query('QUERY', function (err, sql2) {
        // handle err
        cb(/* processed data */)
    });
}

当您调用 getOrderLines 时,您将该回调传入,这允许您使用传递给它的值:

getOrderLines(sql1[i].Id, function (err, result) {
    res.json(result);
});

getOrderLines是一个异步任务,调用这种方式将返回空数组

    ..SalesOrderItems = getOrderLines(sql1[i].Id);

使用异步模块

var async = require('async');
router.get('/salesOrders', function(req, res) {
  // your object here
  var json = {
    Company:{
      SalesOrders: {
        SalesOrder: []
      }
    }
  }; 
  var getSalesOrder = function(callback){
    mysql.query("QUERY", function(err, sql1) {
      for (var i = 0; i < sql1.length; i++) {
        // push item into array
        json.Company.SalesOrders.SalesOrder.push({
          "Id": sql1[i].Id,
          "AccountReference": sql1[i].AccountReference,
          "SalesOrderDate": sql1[i].SalesOrderDate,
          "SalesOrderAddress": [{
            "Forename": sql1[i].billFirstname,
            "Lastname": sql1[i].billLastName,
            "Address": sql1[i].billAddress1
          }],
          "SalesOrderItems": {}
        });
      }
      // job done, trigger next function;
      callback();
    });
  }
  var getOrderLines = function(callback) {
    var orderLineJson = {"Item":[]};
    var dataLength = json.Company.SalesOrders.SalesOrder.length;
    for(var i=0; i<dataLength; i++){
      // do what ever you like with orderId
      var orderId = json.Company.SalesOrders.SalesOrder[i].Id;
      // async query
      mysql.query('QUERY', function(err, sql2) {
        for (var j = 0; j < sql2.length; j++) {
          orderLineJson.Item.push({
            "SKU": sql2[j].name,
            "QtyOrdered": sql2[j].quantity,
            "UnitPrice": sql2[j].price
          });
        }
        json.Company.SalesOrders.SalesOrder[i].SalesOrderItems = orderLineJson;
        // check for the last item
        if(i == dataLength-1)
          callback();
      });
    }
  }
  // run async sequentially
  async.series([getSalesOrder, getOrderLines], function(err, result){
    // finally send the json
    res.json(json);
  });
});