【问题标题】:Mongoose difficulty understanding how to correctly use promises/async awaitMongoose 难以理解如何正确使用 promises/async await
【发布时间】:2018-10-12 18:20:56
【问题描述】:

我有一个 nodejs 后端,它使用 Mongoose 快速处理我的 API 到我的 mongo DB 的路由。我已经更改了代码,使其更易于理解,但实际上我正在构建一个任务列表。

我有一个用于将任务添加到任务列表的端点,我想维护一个任务列表以便稍后执行一些分析。我遇到的问题是我想检查一个任务是否已经存在,如果该任务不存在,那么我想在我的任务模型中创建它,然后将它添加到我的任务列表中。如果它确实存在,那么我只想将它添加到我的任务列表中。

我的第一个想法是在创建任务时在保存操作上使用异步,因为我想避免嵌套大量的承诺,因为这使得它非常不可读。但是当我的 nodejs 服务器启动时,它给了我一个错误SyntaxError: await is only valid in async function,但是从文档中你可以在保存时使用 await,并且我的函数有 async 关键字。所以我不知道我做错了什么。

exports.tasklists_add_task = async (req, res, next) => {
    const id = req.params.tasklistId;

    Task.findOne({ externalId: req.body.externalId })
        .exec()
        .then(doc => {

            let task = doc;

            if (!task) {
                task = new Task({
                    _id: new mongoose.Types.ObjectId(),
                    externalId: req.body.externalId,
                    name: req.body.name
                });

                await task.save();
            }
            tasklist.update({_id: id}, {$push: { tasks: tasks }})
            .select("-__v")
            .exec() 
        })
        .then(result => {
            ...
        })
        .catch(err => { ... })
}

我有 2 个模式一个任务模式

const mongoose = require("mongoose");

const taskSchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    externalId: { type: String, required: true },
    name: { type: String, required: true }
});

module.exports = mongoose.model("Task", taskSchema);

和一个任务列表架构

const mongoose = require("mongoose");

const taskListSchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    user: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true },
    type: { type: String, required: true },
    tasks: [{ type: mongoose.Schema.Types.ObjectId, ref: "Type" }]
});

module.exports = mongoose.model("TaskList", taskListSchema);

我不必在这里使用异步等待,我可以只链接承诺,但我无法弄清楚如何以逻辑可读的方式链接承诺,因为如果它不存在我必须创建任务.

【问题讨论】:

    标签: javascript node.js mongodb


    【解决方案1】:

    await 仅允许在异步函数中使用(前提是您使用的是支持它的环境)。 Await 仅在 async 函数中有效,而您的 await 在非异步回调中 - 只有您的顶级函数是 async。你错过了这里的关键字:

    .then(doc => {
    
    // Should be:
    .then(async doc => {
    

    这样你就告诉你的代码doc 回调是异步函数。但是,当您的环境中有 async/await 时,整个块可能会被重构为这样!

    exports.tasklists_add_task = async (req, res, next) => {
      const id = req.params.tasklistId;
    
      try {
        let task = await Task.findOne({ externalId: req.body.externalId })
          .exec();
    
        if (!task) {
           task = new Task({
             _id: new mongoose.Types.ObjectId(),
             externalId: req.body.externalId,
             name: req.body.name
           });
    
           await task.save();
        }
    
        const result = await tasklist.update({_id: id}, {$push: { tasks: tasks }}).select("-__v").exec();
      } catch (err) {
        // Error handling here
      } 
    }
    

    在大多数情况下,无需混合使用 async/awaitthens。将其视为处理承诺并将then/catch 隐藏在顺序可读代码后面的奇特方式。

    我建议调整代码,使其看起来像提出的解决方案(大量混合 Promises 和 Async/Await 被认为有点反模式)。

    【讨论】:

    • 这正是我想要的答案,谢谢,现在我的 async 应该在我的 findOne 上就很有意义了。我还没有真正研究过异步等待,所以我非常感谢重构。
    猜你喜欢
    • 1970-01-01
    • 2016-01-09
    • 1970-01-01
    • 2020-08-23
    • 2021-12-15
    • 2019-07-20
    • 2021-07-30
    • 2018-04-27
    • 2023-01-05
    相关资源
    最近更新 更多