猫鼬 findById 的异步/等待行为

Posted

技术标签:

【中文标题】猫鼬 findById 的异步/等待行为【英文标题】:async/await behaviour of mongoose findById 【发布时间】:2018-04-13 17:38:03 【问题描述】:

我有以下代码:

const checkForRecord = async (id) => 

    let model = mongoose.model('User');

    let query = 
    query.dummy = false; <== This is field is here to forcely cause an error, as it is not present on my User model.
    let result = await model.findById(id, query);

    console.log('Code reached here !!!');
    console.log(result);

我收到以下错误:

(node:6680) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): CastError: Cast to ObjectId failed for value ...

我的console.logs 甚至都没有被调用。

为什么没有设置错误,因为我的操作是异步的?

我都试过了:

let result = await model.findById(id, query);

let result = await model.findById(id, query).exec();

同样的行为。

【问题讨论】:

使用 async/await 您应该使用 try/catch 来处理 awaited 结果的错误,请参阅几乎所有关于 async/await 的教程以获取示例 .... 将结果设置为错误令人困惑,不是吗?你怎么知道结果是有效的还是错误的? 该错误似乎表明您传递给checkForRecord 的任何内容,因为id 不能转换为ObjectId,您能告诉我们您的id 是什么吗? 我认为 OP 是故意导致错误 - 看到这个 - &lt;== To cause an error, this field is not used const checkForRecord = async (id) ... 是语法错误。代码实际上是什么样子的?箭头函数? @T.J.Crowder 我的话... 【参考方案1】:

我的 console.logs 甚至没有被调用。

这是正确的行为。这是一个 async 函数,而您是 awaiting 一个返回承诺的函数。这意味着拒绝被建模为异常,终止checkForRecord 函数。

为什么该错误没有设置为result,因为我的操作是异步的?

因为它不是分辨率值(这是await 给你的),所以它是拒绝/例外。看看checkForRecord 的去糖版本是什么样子可能会有所帮助,将asyncawait 替换为它们的底层promise 操作:

// checkForRecord with async/await desugared to their underyling Promise operations
const checkForRecord = (id) => 

    let model = mongoose.model('User');

    let query = ;
    query.dummy = false; // <== To cause an error, this field is not used
    return model.findById(id, query).then(value => 
        let result = value;
        console.log('Code reached here !!!');
        console.log(result);
    );
;

如您所见,您无法访问console.logs,因为它们位于解析处理程序中;但是拒绝不会转到解决处理程序,而是转到拒绝处理程序。

明确一点:我并不是说您需要更改 checkForRecord。我只是向您展示async/await 在运行时(实际上)变成了什么。

您的checkForRecord 很好(除了缺少=&gt; 并且没有评论query.dummy 行上的评论)。你可以在 async 函数中这样使用它:

try 
    checkForRecord(someId);
 catch (e) 
    // Handle the error here

...如果不在 async 函数中,也可以这样:

checkForRecord(someId).catch(e => 
    // Handle the error here
);

【讨论】:

嗯。谢谢你的解释。

以上是关于猫鼬 findById 的异步/等待行为的主要内容,如果未能解决你的问题,请参考以下文章

Mongoose 中的 Model.findById() - 异步/等待 [重复]

Javascript异步等待不等待猫鼬等待

猫鼬异步/等待

在猫鼬中执行 CRUD 操作时异步/等待

异步函数不等待Promise

带有异步操作的猫鼬游标