I have a piece of code in which i run 2 promises.
我有一段代码,其中我运行2个承诺。
The problem is that the second promise runs while the first promise is still running. this is causing me so many problems. I want that the second promise will not run, until i get an answer from the first promise.
问题是第二个承诺在第一个承诺仍在运行时运行。这给我带来了很多问题。我希望第二个承诺不会运行,直到我得到第一个承诺的答案。
I don't want to put the second promise inside the first one.
我不想把第二个承诺放在第一个承诺里面。
Somebody knows how can i achieve this? Is it possible to use Async await?
有人知道我怎么能做到这一点?可以使用Async await吗?
Here is my code:
这是我的代码:
router.post("/", (req, res) => {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
//first check if the seats are taken
/*
this is working. but gives me
"(node:14552) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 3): Error: Can't set
headers after they are sent."
when the seats are taken. check it out
*/
Show.findById(req.body._ShowId).then(show => {
req.body.ticketsPositions.forEach(element => {
console.log('checking: ' + element[0] + "-" + element[1]);
if (show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1])){
console.log('seat are already taken!');
return res.status(400).json({'message': 'Seats are already taken!'})
}
});
});
order.save().then(newOrder => {
console.log("Order saved successfully");
res.json(newOrder);
}, err => {
res.send(err);
});
});
Many thanks!
非常感谢!
2 个解决方案
#1
4
I don't want to put the second promise inside the first one.
我不想把第二个承诺放在第一个承诺里面。
Well...that's what you do, effectively:
嗯......这就是你做的,有效的:
router.post("/", (req, res) => {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
Show.findById(req.body._ShowId)
.then(show => {
// Make sure all seats are okay; notice we don't do `res.send` here,
// we just see if every seat is available
const seatsOkay = req.body.ticketPositions.every(element => {
console.log('checking: ' + element[0] + "-" + element[1]);
return !show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1]);
});
if (seatsOkay) {
// Yes, order
return order.save().then(newOrder => {
console.log("Order saved successfully");
res.json(newOrder);
});
} else {
// Nope, send response -- ONCE, not in the ticketPositions loop
console.log('seat are already taken!');
res.status(400).json({'message': 'Seats are already taken!'})
});
})
.catch(err => {
res.send(err);
});
});
On any vaguely-modern version of Node, you can use an async
function instead. Just be sure to catch errors, since router.post
won't handle errors for you (you might look at koa):
在任何模糊的现代版本的Node上,您可以使用异步函数。请务必捕获错误,因为router.post不会为您处理错误(您可以查看koa):
router.post("/", async (req, res) => {
try {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
// Get this show
const show = await Show.findById(req.body._ShowId);
// Make sure all seats are okay
const seatsOkay = req.body.ticketPositions.every(element => {
console.log('checking: ' + element[0] + "-" + element[1]);
return !show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1]);
});
if (seatsOkay) {
// Yes, order
const newOrder = await order.save();
console.log("Order saved successfully");
res.json(newOrder);
} else {
// Nope, send error response
console.log('seat are already taken!');
res.status(400).json({'message': 'Seats are already taken!'})
});
} catch (err) {
res.send(err);
}
});
#2
3
Here is a version using async/await. Amazing how it flattens things out and makes the error handling simplified. The catch will catch all exceptions in both awaits (thrown or rejected), and thrown in the method itself.
这是一个使用async / await的版本。令人惊讶的是它如何平整事物并简化错误处理。 catch将捕获等待(抛出或拒绝)中的所有异常,并抛出方法本身。
Also, you don't want to throw inside a forEach. Use filter instead to find the condition you are looking for. If you need async stuff in the loop, that's another issue altogether.
此外,你不想扔进一个forEach。请使用过滤器来查找您要查找的条件。如果你需要循环中的异步内容,那就完全是另一个问题了。
router.post("/", async(req, res) => {
try {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
var show = await Show.findById(req.body._ShowId)
var taken = req.body.ticketsPositions.find(element => {
return show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1])
});
if (taken) {
return res.status(400).json({
'message': 'Seats Taken'
})
}
var newOrder = await order.save().json()
res.send.json(newOrder);
} catch (err) {
res.status(500).send(err)
}
});
#1
4
I don't want to put the second promise inside the first one.
我不想把第二个承诺放在第一个承诺里面。
Well...that's what you do, effectively:
嗯......这就是你做的,有效的:
router.post("/", (req, res) => {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
Show.findById(req.body._ShowId)
.then(show => {
// Make sure all seats are okay; notice we don't do `res.send` here,
// we just see if every seat is available
const seatsOkay = req.body.ticketPositions.every(element => {
console.log('checking: ' + element[0] + "-" + element[1]);
return !show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1]);
});
if (seatsOkay) {
// Yes, order
return order.save().then(newOrder => {
console.log("Order saved successfully");
res.json(newOrder);
});
} else {
// Nope, send response -- ONCE, not in the ticketPositions loop
console.log('seat are already taken!');
res.status(400).json({'message': 'Seats are already taken!'})
});
})
.catch(err => {
res.send(err);
});
});
On any vaguely-modern version of Node, you can use an async
function instead. Just be sure to catch errors, since router.post
won't handle errors for you (you might look at koa):
在任何模糊的现代版本的Node上,您可以使用异步函数。请务必捕获错误,因为router.post不会为您处理错误(您可以查看koa):
router.post("/", async (req, res) => {
try {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
// Get this show
const show = await Show.findById(req.body._ShowId);
// Make sure all seats are okay
const seatsOkay = req.body.ticketPositions.every(element => {
console.log('checking: ' + element[0] + "-" + element[1]);
return !show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1]);
});
if (seatsOkay) {
// Yes, order
const newOrder = await order.save();
console.log("Order saved successfully");
res.json(newOrder);
} else {
// Nope, send error response
console.log('seat are already taken!');
res.status(400).json({'message': 'Seats are already taken!'})
});
} catch (err) {
res.send(err);
}
});
#2
3
Here is a version using async/await. Amazing how it flattens things out and makes the error handling simplified. The catch will catch all exceptions in both awaits (thrown or rejected), and thrown in the method itself.
这是一个使用async / await的版本。令人惊讶的是它如何平整事物并简化错误处理。 catch将捕获等待(抛出或拒绝)中的所有异常,并抛出方法本身。
Also, you don't want to throw inside a forEach. Use filter instead to find the condition you are looking for. If you need async stuff in the loop, that's another issue altogether.
此外,你不想扔进一个forEach。请使用过滤器来查找您要查找的条件。如果你需要循环中的异步内容,那就完全是另一个问题了。
router.post("/", async(req, res) => {
try {
if (!checkIfOrderValid(req.body)) {
return res.sendStatus(400);
}
let order = new Order(req.body);
order._UserId = '5b58836ed741e92d7416002e';
var show = await Show.findById(req.body._ShowId)
var taken = req.body.ticketsPositions.find(element => {
return show.showTakenSeats.hasOwnProperty(element[0] + "-" + element[1])
});
if (taken) {
return res.status(400).json({
'message': 'Seats Taken'
})
}
var newOrder = await order.save().json()
res.send.json(newOrder);
} catch (err) {
res.status(500).send(err)
}
});