【问题标题】:how can i make sure that the code will not run after a promise?我如何确保代码在承诺后不会运行?
【发布时间】:2018-08-07 18:36:08
【问题描述】:

我有一段代码在其中运行 2 个 promise。

问题是第二个 promise 运行时第一个 promise 仍在运行。这给我带来了很多问题。 我希望第二个承诺不会运行,直到我从第一个承诺中得到答案。

我不想将第二个承诺放在第一个承诺中。

有人知道我怎么能做到这一点?是否可以使用异步等待?

这是我的代码:

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

非常感谢!

【问题讨论】:

  • 另外说明:在.forEach() 中返回 res.status(...).json(...)` 是个问题。它不会停止您的 .forEach() 循环,您可能会尝试发送多个响应,因此部分设计有点混乱。
  • 您可以通过链接 promise(无需嵌套)或使用 async/await 来实现您的目标。如果您想进行一些研究,则有数千篇关于这两个方面的文章。

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


【解决方案1】:

我不想将第二个承诺放在第一个承诺中。

嗯......这就是你所做的,有效地:

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

【讨论】:

    【解决方案2】:

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

    另外,你不想在 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)
      }
    });

    【讨论】:

      猜你喜欢
      • 2020-04-12
      • 2019-01-21
      • 1970-01-01
      • 2023-01-23
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 2020-02-21
      • 2020-07-26
      相关资源
      最近更新 更多