猫鼬难以理解如何正确使用Promise / async await

时间:2018-10-12 10:12:16

标签: javascript node.js mongodb

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

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

我的第一个想法是在创建任务时在保存操作上使用异步,因为我想避免嵌套承诺的数量,因为这使它非常难以理解。但是,当我的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);

我不必在这里使用async await,我可以只链接promise,但是我无法解决如何以逻辑可读的方式链接promise,因为如果不存在,我必须创建任务

1 个答案:

答案 0 :(得分: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/awaitthen混合使用。可以将其视为处理承诺并将then/catch隐藏在顺序易读的代码后面的绝佳方式。

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