await 仅在异步函数中有效 - 当使用 Mongoosejs exec() 时



我正在将一个快乐的项目移植到 v17 并在移动到 async/await 时遇到一些 Mongoose 问题。

对于我的任何使用"await"的代码,在模型(猫鼬(上,例如对象:

const result = await User.findOne({email: email}).exec();

运行"节点服务器.js时出现以下异常

await User.findOne({}).exec();
^^^^^
SyntaxError: await is only valid in async function
at new Script (vm.js:74:7)
at createScript (vm.js:246:10)
at Object.runInThisContext (vm.js:298:10)
at Module._compile (internal/modules/cjs/loader.js:670:28)
at Object.Module._extensions..js 
(internal/modules/cjs/loader.js:713:10)
at Module.load (internal/modules/cjs/loader.js:612:32)
at tryModuleLoad (internal/modules/cjs/loader.js:551:12)
at Function.Module._load (internal/modules/cjs/loader.js:543:3)
at Module.require (internal/modules/cjs/loader.js:650:17)
at require (internal/modules/cjs/helpers.js:20:18)

我正在运行节点 v10.2.0 和猫鼬 5.1.2,但不明白为什么我会收到错误。

mongoosejs 文档明确指出,在使用 async/await 时应该使用 exec(( 返回承诺,如此处所述

有什么建议吗?

await只能在使用async关键字声明的函数中使用。

async function doSomething() {
let result = await someMongoooseFunctionThatReturnsAPromise();
// use result here
}

await不能在async函数之外使用。 这就是你的错误告诉你的,它与猫鼬完全无关。 它与调用猫鼬函数的代码的结构有关。

注意:任何节点.js事件驱动的代码都已经在函数中,因此要在该函数中使用await,您所要做的就是将async关键字添加到包含函数定义的字符串中。 如果该函数的调用方不需要任何返回结果,则无需进一步更改。 如果该功能的调用方期望返回结果,则必须调整调用代码以期望从async声明的函数返回承诺。


同样值得理解的是,async函数总是返回一个承诺。 虽然您可以像常规顺序代码一样编写它:

async function doSomething() {
let result = await someMongoooseFunctionThatReturnsAPromise();
// use result here
result++;
return result;
}

此函数实际上返回一个承诺,该承诺的解析值将是函数的返回值。 因此,当您使用这样的async函数时,您必须使用返回的 promise:

doSomething().then(finalResult => {
console.log(finalResult);
});

因此,在您的特定代码中,如果您要使用await,它需要位于async函数中:

async function someFunc() {
const result = await User.findOne({email: email}).exec();
// now this will work and you can use result here
}

或者,您可以改用.then()

User.findOne({email: email}).exec().then(result => {
// process result here
// continue with other code that uses result here
});

注意:要使用async/await时处理错误,您有两种选择:

  1. 您可以在任何async声明的函数中使用传统try/catchtry/catch将捕获来自await的任何被拒绝的承诺。

  2. 如果您不使用 try/catch 并且函数中的await被拒绝,则函数本身返回的承诺将被拒绝,函数的调用方将获得被拒绝的承诺。

所以,这取决于情况。 如果你想在本地处理拒绝,那么你必须在await周围使用 try/catch(就像你对.catch()一样。 如果您希望拒绝冒泡给调用者,以便他们看到被拒绝的承诺,那么您不需要try/catch因为 Javascript 解释器将通过拒绝async函数返回的承诺来自动冒泡被拒绝的await

你需要像这样的异步函数中包围你的代码

async function fetchFun() {
const result = await User.findOne({email: email}).exec();
console.log('Results fetched!'); //etc
}
fetchFun(); // <--

注意:正如我用箭头指出的那样,您仍然必须在没有await的情况下调用此函数,因为您的代码 async/await 代码必须有一些入口(如 C 中的main()(,并且该入口函数不能用await调用

最新更新