Reputation: 35
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
Upvotes: 1
Views: 422
Reputation: 24565
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.
Upvotes: 1