1

i'm working on API to receive the order items on each of orders. I have problem to received the order items details. Please look on the codes below.

Controller.orderLists = (req, res, next) => {
    --- some code ---
    Model.Orders.findAll({
        attributes: [
            'order_id',
            'status'
        ],
        where: {
            customer_id: req.customer_id,
            status: 1
        }
        group: ['orders.order_id'],
        limit: 1,
        subQuery: false
    }).then((orderList) => {
        if (!_.isEmpty(orderList)) {
            var results = [];
            var index = 0;
            orderList.forEach(function (order) {
                getOrderInfo(order.order_id, function (err, items) {
                    console.log(items);
                    results[index] = {
                        'order_id': order.order_id,
                        'status': order.status,
                        'order_item': items
                    };

                    index++;
                    return results;
                });
            });

            res.json({
                status: 1,
                msg: 'Order Lists',
                data: results
            });
        } else {
            res.json({
                status: 1,
                msg: 'Order not found',
                data: results
            });
        }
    }).catch((err) => {
        console.error('ERROR :', err);
        res.json({
            status: -1,
            msg: 'An error occured'
        });
    });
});

From the model, I get the lists of order id. From the lists will run each of the order to retrieved order items. I have tried many attempt code but looks no luck.

function getOrderInfo(order_id, callback) {
    --- 1st attempt code ---
    return Model.OrderItem.find({
        attributes: [
            [Sequelize.literal('sum(quantity)'), 'total_quantity']
        ],
        where: {
            order_id: order_id
        }
    }).then((order_data) => {
        callback(null, JSON.stringify(order_data.dataValues));
    });
    --- end 1st attempt code ---

    --- 2nd attempt code ---
    return Sequelize.model('order_items').findOne({
        attributes: [
            [Sequelize.literal('sum(quantity)'), 'total_quantity']
        ],
        where: {
            order_id: order_id
        }
    }).then((data) => {
        return callback(null, data.dataValues);
    });
    --- end 2nd attempt code ---

    --- 3rd attempt code ---
    var sql = "SELECT SUM(quantity) AS total_quantity FROM order_items WHERE order_id = " + order_id;
    Sequelize.query(sql, {
        plain: true, 
        type: Sequelize.QueryTypes.SELECT
    }).then((order) => {
        callback(null, order);
    });
    --- end 3rd attempt ---
}

The current and expected results:

Current: 
{
    "status": 1,
    "msg": "Order Lists",
    "data": []
}

Expected:
{
    "status": 1,
    "msg": "Order Lists",
    "data": [
        {
            "order_id": 1234,
            "status": 1,
            "order_item": {
                "total_quantity": "3"
            }
        },{
            --- some data ---
        }
    ]
}

The expected data should come from results variable. The log show some warning about promises.

0|AppServer:  | 2020-05-14 14:12:09 +08:00: (node:4740) Warning: a promise was created in a handler but was not returned from it
0|AppServer:  | 2020-05-14 14:12:09 +08:00:     at Function.Promise.attempt.Promise.try (c:\xampp\htdocs\api\node_modules\bluebird\js\release\method.js:29:9)

I think it might be problem with async and await scripts. How to make the scripts to hold on and let getOrderInfo() execute first then proceed next step?

Please I need help. Thanks

1 Answer 1

1

getOrderInfo operates async and returns a promise. Since you don't await it, res.json(...) is executed before the promises resolve. You can fix by awaiting all promises and send the response in the then handler:

...
const orderPromises = [];
orderList.forEach(function (order) {
    orderPromises.push(getOrderInfo(order.order_id));
});

Promise.all(orderPromises)
.then(results => {
    res.json({
        status: 1,
        msg: 'Order Lists',
        data: results
    });
});
...

function getOrderInfo(order_id) {
    return Model.OrderItem.findOne({
        attributes: [
            [Sequelize.literal('sum(quantity)'), 'total_quantity']
        ],
        where: {
            order_id: order_id
        }
    })
    .then(order => {
        return {
            'order_id': order.order_id,
            'status': order.status,
            'order_item': items
        }
    })
}

Note that I recommend using async/await instead of pure promises as it greatly increases the readability of your code -> check this for more information.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.