首页 > 解决方案 > 输出不正确,需要同步for循环

问题描述

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

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

标签: node.jspromise

解决方案


您正在resolveing 立即执行,而不是在提供给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稍后完成

相反,您可能应该做这样的事情,在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调用者现在将继续,因为它已被告知该函数已解决

您需要在调用方继续之前需要实际完成查询的任何函数中遵循此模式。


您还应该考虑利用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

推荐阅读