Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct syntax for a method declared as async?

I stumbled upon the following ES6 method during a rewiew:

async getUsers(res) {
  User.findAll().then(users => res.json(users));
}

This seems buggy to me. I would have expected the following:

async getUsers(res) {
  return User.findAll().then(users => res.json(users));
}

But then, I know that async has many tricks such as auto-wrapping promises, so is my intuition correct?

like image 357
Gurg Hackpof Avatar asked Oct 30 '22 12:10

Gurg Hackpof


1 Answers

The code as it is written (without the return) is likely fine as long as the caller does not need access to the asynchronously retrieved value.

First off, async is needed as part of your function definition ONLY if you plan on using await inside the function. If you aren't using await inside (which your code does not show), then the async part of the definition is not needed. So, it could probably be just this:

getUsers(res) {
  User.findAll().then(users => res.json(users));
}   

Second, if a caller wants to use await on the getUsers() function, then it needs to return a promise (as you proposed). If the caller will not use await with it or otherwise need any access to a return value, then the return is not necessary. So, if you wanted to use await on this function, then it should probably be this:

getUsers(res) {
  // return promise so caller can get async value
  return User.findAll().then(users => {
      res.json(users);
      return users;      // return value so caller can get access to the value
  });
}

So, the original code may be just fine as long as the caller is never expecting an asynchronous return value from that function (which is possible here because the result of the async operation is being sent with res.json() and that may be the only result that is needed. As far as await/async are concerned, you only have to return a promise from functions that you plan to use await on.


To recap:

  1. async is only needed if you plan on using await inside the function. Your function probably doesn't even need the async keyword on it at all.
  2. A returned promise is only needed if the caller wants to be able to get access to the asynchronous response either via a traditional f().then() or via let x = await f().
  3. A caller can await a function that is not marked as async. The await will get the return value from the function and, if the return value is not a promise it will wrap it in a resolved promise. If it is a promise, it will wait for it to resolve.

FYI, this is a very good, short and sweet review of async/await and how they interact with promises.

like image 104
jfriend00 Avatar answered Nov 15 '22 04:11

jfriend00