我如何确保承诺后代码不会运行?

时间:2018-08-07 18:36:08

标签: javascript node.js ecmascript-6 async-await es6-promise

我有一段代码,其中我有2个诺言。

问题是第二个承诺在第一个承诺仍在运行时运行。这给我造成了很多问题。 我希望第二个承诺不会执行,直到我从第一个承诺得到答复。

我不想把第二个诺言放在第一个诺言中。

有人知道我该如何实现?可以使用异步等待吗?

这是我的代码:

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);
    });
});

非常感谢!

2 个答案:

答案 0 :(得分:4)

  

我不想把第二个诺言放在第一个诺言中。

嗯...这就是您要做的,有效地:

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);
        });
});

在任何模糊的现代版本的Node上,都可以使用async函数。只需确保捕获错误,因为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);
    }
});

答案 1 :(得分:3)

这是使用async / await的版本。令人惊讶的是,它使事情变得平整,并简化了错误处理。捕获将捕获所有等待(抛出或拒绝)中的所有异常,并抛出该方法本身。

此外,您也不想扔进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)
  }
});