【问题标题】:node.js convert my express method to async/awaitnode.js 将我的 express 方法转换为 async/await
【发布时间】:2018-04-24 04:48:21
【问题描述】:

我怀疑将我的 express 方法转换为使用 async/await。

此时,我的方法如下:

app.post('/', (req, res) => {
const body = req.body;

let hospital = new Hospital({
    name: body.name,
    user: req.user._id
});

hospital.save((err, hospitalCreated) => {
    if (err) {
        return res.status(400).json({
            ok: false,
            mensagem: "Error to create hospital",
            errors: err
        });
    }

    res.status(201).json({
        ok: true,
        hospital: hospitalCreated
    });
});

});

作为我的新节点,我尝试这样写:

app.post('/', async (req, res) => {
const body = req.body;

let hospital = new Hospital({
    name: body.name,
    user: req.user._id
});

await hospital.save((err, hospitalCreated) => {
    if (err) {
        return res.status(400).json({
            ok: false,
            mensagem: "Error to create hospital",
            errors: err
        });
    }

    res.status(201).json({
        ok: true,
        hospital: hospitalCreated
    });
});

这是实现这一目标的正确方法吗?我必须使用 try/catch 吗?最好的方法是什么?

谢谢

【问题讨论】:

  • hospital.save() 是您可以分享的方法吗?或者它是另一个图书馆?
  • @MagdKudama 我相信他使用猫鼬,但原生 mongo 驱动器也可以。
  • 开始阅读有关 async/await 是什么以及不是什么的文档。 MDN.
  • @MagdKudama 我正在使用猫鼬。你可以在这里了解更多:developer.mozilla.org/en-US/docs/Learn/Server-side/…
  • 我不知道你想使用async/await的原因是什么。您可以获得的好处是,如果出现错误,它们将落入错误处理程序,并且您的代码看起来会更清晰。但是你需要用.catch(next)包装你的中间件

标签: node.js express async-await


【解决方案1】:

asyncawait 生成器的目的是避免使用回调。如果save 方法总是返回Promise 并调用回调,那么您所做的可能会起作用,但是这种方法破坏了生成器的全部目的。您应该删除回调并改用trycatch

try {
    await hospital.save();
    res.status(201).json({
        ok: true,
        hospital: hospital
    });
} catch (err) {
    res.status(400).json({
        ok: false,
        mensagem: "Error to create hospital",
        errors: err
    });
}

【讨论】:

  • 你的答案总是会出错,因为没有hospitalCreated。为避免这种情况,只需将其替换为 hospital
【解决方案2】:

我认为您可以使用 Promise resolve 将 hospital.save 移动到异步函数,然后使用 await 获取响应并使用 catch 从 Promise 中获取错误,例如:

使用猫鼬回调更新:

function saveHospital(hospital) {
        return new Promise((resolve, reject) => {
            hospital.save((err, hospitalCreated) => {
                if (err) {
                    reject(error);
                }

                resolve(hospitalCreated);
            });
        });
    }

    app.post('/', async (req, res) => {
        const body = req.body;

        let hospital = new Hospital({
            name: body.name,
            user: req.user._id
        });

        try {
            const hospitalCreated = await saveHospital(hospital)

            res.status(201).json({
                ok: true,
                hospital: hospitalCreated
            });
        } catch(error) {
            res.status(400).json({
                ok: false,
                mensagem: "Error to create hospital",
                errors: err
            })
        }
    }

【讨论】:

  • 这是一个糟糕的答案,(1)如果您创建文档失败,您将收到错误提示,您无法发送两次标头。 catch 链中的最后一个 return 是多余的; (2) Mongoose返回一个promise,你不需要Promise的额外衣服。
  • 对于 (1) 这就是为什么我在 res.status(400).json({ ok: false, mensagem: "Error to create hospital", errors: err }) 和 (2) 之后添加 return 的原因,确定您是否使用猫鼬的承诺,只需将 await saveHospital(hospital) 更改为 await hospital.save(),但如果您使用带有回调的猫鼬,可能是一种方法。
  • 你还是不明白我的意思,你在 catch 中的参数是一个函数,它有它自己的词法范围。你正在做的是告诉计算机你在catch 中完成了你的函数执行,如果你添加了.then(),那么函数将收到返回值,即undefined。您添加的return 不会在其父范围内停止执行。
  • 另外,我认为您对Promise 的概念有点不稳定。对于我的第二点,因为如果没有提供回调,猫鼬会返回一个承诺,你不需要处理回调。如果遇到错误,直接在 catch 链上处理即可,这就是 promise 如此美丽的原因。
  • @LeoLi 明白了,是我的理解错误。但是我对 mongoose 有一个疑问,你说如果你不提供回调,mongoose 会返回一个 Promise,这个功能在版本 >= 5 上可用?
猜你喜欢
  • 2012-10-25
  • 2019-11-08
  • 2014-02-16
  • 1970-01-01
  • 1970-01-01
  • 2019-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多