输出不正确,需要同步循环

时间:2018-06-05 16:03:12

标签: node.js promise

exports.calculateGstBaseOnInput = function(req, res) {
    console.log("welcome");
    for (var item of req.body.so_items) {
        req.productid = item.productid;
        req.qty = item.qty;
        getItemDetail(req, res).then(function(result) {
            return getCartItems(req, res);
        }).then(function(result) {
            return calculateGST(req, res);
        })
    }
}

getItemDetail = function(req, res) {
    return new Promise(function(resolve, reject) {
        console.log("inside getItemDetail");

        var SQL = "mysql query";
        mysqlConnect.query(SQL, function(err, result, fields) {
            if (err) {
                console.log("inside err");

                res.json({ status: 'Failure', statusMessage: 'item does not exist' });
            } else if (result.length < 0) {
                console.log("inside length 0");

                res.json({ status: 'Failure', statusMessage: 'item does not exist' });
            } else {
                req.itemdetail = result;
                console.log("price inside getitemdetail= ", req.itemdetail[0].price);

                //callback();
            }
        });
        resolve('done');
    });
}

getCartItems = function(req, res) {
    return new Promise(function(resolve, reject) {
        console.log("inside getCartItems");
        var SQL = "mysql query";
        mysqlConnect.query(SQL, function(err, result, fields) {
            if (err) {
                res.json({ status: 'Failure', statusMessage: 'item does not exist' });
            } else if (result.length < 0) {
                res.json({ status: 'Failure', statusMessage: 'item does not exist' });
            } else {
                req.cartItems = result;
                //callback();
            }
        });
        resolve('done');
    });
}

calculateGST = function(req, res) {
    return new Promise(function(resolve, reject) {
        console.log("inside calculateGST");

        if (req.userDetails[0].is_gst_included) {
            //total = req.qty * req.itemdetail[0].price;
            // console.log("price = ",req.itemdetail[0].price);
            //callback();
        } else {
            //total = req.qty * req.itemdetail[0].price;
            //console.log("price = ",req.itemdetail[0].price);
            //total = req.qty * req.itemdetail[0].price;

        }

        resolve('done');
    });
}

实际输出:

inside getItemDetail
inside getItemDetail
inside getCartItems
inside getCartItems
inside calculateGST
inside calculateGST

预期输出(我想要的输出):

inside getItemDetail
 inside getCartItems
    inside calculateGST
    inside getItemDetail
    inside getCartItems
    inside calculateGST

如何在不设置任何时间的情况下实现这一目标。

1 个答案:

答案 0 :(得分:1)

resolve立即{而不是在提供给mysqlConnect.query()的回调中解析。

考虑getItemDetail函数的缩写版本:

function getItemDetail(req, res) {
    return new Promise(function(resolve, reject) {
        var SQL = "mysql query";
        mysqlConnect.query(SQL, function(err, result, fields) {
            // Stuff
        });
        resolve('done');
    });
}

这是逻辑:

  1. 创建新承诺
  2. 开始query
  3. resolve()
  4. 所谓的getItemDetail做了什么,因为getItemDetail解决了
  5. query稍后完成
  6. 相反,您可能应该这样做,其中resolve位于query回调中:

    function getItemDetail(req, res) {
        return new Promise(function(resolve, reject) {
            var SQL = "mysql query";
            mysqlConnect.query(SQL, function(err, result, fields) {
                // Stuff
                resolve('done');
            });
        });
    }
    

    这里的逻辑是:

    1. 创建新承诺
    2. 开始query
    3. getItemDetail来电者不应该做任何事情,因为getItemDetail尚未解决
    4. query在某个时刻结束并触发回调调用resolve
    5. getItemDetail调用者现在将继续,因为已经告知函数已解决
    6. 在调用者继续前需要查询实际完成的任何函数中,您需要遵循此模式。

      您还应考虑利用async/await。以您的代码为基础考虑这个缩写示例:

      const mysqlConnect = {
          query(sql, cb) {
              setTimeout(() => {
                  cb(null, ["foo"], ["bar"]);
              });
          }
      };
      
      (async function() {
          const t = await calculateGstBaseOnInput({
              body: {
                  so_items: ["a", "b", "c"]
              }
          });
      }());
      
      async function calculateGstBaseOnInput(req, res) {
          for (var item of req.body.so_items) {
              const itemDetail = await getItemDetail(req, res);
              const cartItems = await getCartItems(req, res);
              const gst = await calculateGST(req, res);
          }
      }
      
      function getItemDetail(req, res) {
          console.log("getItemDetail");
          return new Promise(function(resolve, reject) {
              var SQL = "mysql query";
              mysqlConnect.query(SQL, function(err, result, fields) {
                  // Stuff
                  resolve('done');
              });
          });
      }
      
      function getCartItems(req, res) {
          return new Promise(function(resolve, reject) {
              console.log("---getCartItems");
              var SQL = "mysql query";
              mysqlConnect.query(SQL, function(err, result, fields) {
                  // Stuff
                  resolve('done');
              });
          });
      }
      
      function calculateGST(req, res) {
          return new Promise(function(resolve, reject) {
              console.log("------calculateGST");
              // Stuff
              resolve('done');
          });
      }
      

      输出:

      getItemDetail
      ---getCartItems
      ------calculateGST
      getItemDetail
      ---getCartItems
      ------calculateGST
      getItemDetail
      ---getCartItems
      ------calculateGST