await is only valid in async function - when using mongoosejs exec()

谁都会走 提交于 2020-01-14 05:52:28

问题


I am porting a Hapi project to v17 and running into some issues with Mongoose when moving to async/await.

With any of my code that uses 'await', on a model (mongoose), object for example:

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

I get the following exception when running 'node server.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)

I am running node v10.2.0 and mongoose 5.1.2 and cannot understand why I am getting the error.

The mongoosejs documentation clearly states that one should use exec() to return the promise when using async/await as stated here

Any suggestions?


回答1:


await can only be used INSIDE a function that is declared with the async keyword.

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

await cannot be used outside an async function. That's what your error is telling you and it has nothing to do with mongoose at all. It has to do with the structure of YOUR code that is calling the mongoose function.

NOTE: Any node.js event driven code is ALREADY inside a function so to use await in that function, all you have to do is to add the async keyword to that containing function definition. If the caller of that function is not expecting any return result, then no further changes are required. If the caller of that funcition is expecting a return result, then you have to adapt the calling code to expect a promise to be returned from the async declared function.


It's also worth understanding that an async function ALWAYS returns a promise. While you may write it like regular sequential code:

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

This function is actually returning a promise and the resolved value of that promise will be the return value of the function. So, when you use an async function like this, you have to use the returned promise:

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

So, in your specific code, if you're going to use await, it needs to be inside an async function:

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

Alternatively, you can use .then() instead:

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

NOTE: To handle errors when using async/await, you have two choices:

  1. You can use traditional try/catch inside any async declared function and the try/catch will catch any rejected promises from await.

  2. If you don't use try/catch and an await inside your function rejects, then the promise that the function itself returns will become rejected and the caller of your function will get the rejected promise.

So, it depends upon the situation. If you want to handle a rejection locally, then you must use try/catch around await (much like you would with .catch(). If you want the rejecting to bubble up to the caller so they will see the rejected promise, then you don't need the try/catch as the Javascript interpreter will automatically bubble a rejected await by rejecting the promise that the async function returns.




回答2:


You need to surround your code in an async function like this

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

  console.log('Results fetched!'); //etc
}

fetchFun(); // <--

Note: You still have to call this function without await as I pointed out by arrow because there has to be some entrance to your code async/await code (like main() in C) and that entrance function cannot be called with await



来源:https://stackoverflow.com/questions/50518069/await-is-only-valid-in-async-function-when-using-mongoosejs-exec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!