24

I would like to do the following and keep in mind it actually works for me. my question is what happens and Is possible to call async usrs() func from non async componentDidMount() func? if it is not possible why it is working for me by calling this.usrs(usrs) instead of await this.usrs(usrs);

let outState = {};
class A extends Component{
  componentDidMount(){
   this.usrs(usrs);
  }
  getData(usr){
    return db.collection('a/'+usr+'/bb').get().then(snap=>{
      for(i = snap.docs.length-1; i>=0; i--){
         outState[usr] = [...outState[usr], snap.docs[i].data()];
         if(i === 0) return outState;
      }
     return false;
    });
  }

  async usrs(usrs){

   let os = {}, data = {};

    for(i = usrs.length-1; i>=0; i--){

       os = await this.getData(usrs[i]);
       if(os){
          data = { ...data, ...os };
          if (i === 0) {
             this.setState({ ...this.state, ...data });
          }
       }

    }

  }

}
Iqbal Jan
  • 644
  • 3
  • 7
  • 20
  • You can call .then method on any async function instead of awaiting the call – binariedMe Mar 06 '19 at 09:24
  • For reference, I just came across this article that seems to describe variations of using and not using `async`: https://dev.to/codeprototype/async-without-await-await-without-async--oom – user1063287 Aug 05 '19 at 08:10

5 Answers5

28

You only need await if the caller needs to wait for the function to be done, for instance when it needs the result of the function, or when it needs to wait for some state/data change that the function causes. If there is no such dependency, you can just 'fire and forget', by not using the await keyword.

As others mentioned, you could use .then as well, but the basic rule is the same: you do that, when you have something specific to do after the function is done. It can be omitted otherwise.

So concretely: With 'caller', I simply mean the function that calls the async function. In your case that would be componentDidMount. The options are then quite simple:

  1. Keep as is. usrs() will be run in the background completely and componentDidMount will continue running until its end.
  2. Use await, so componentDidMount will wait for the return of usrs().
  3. Use usrs().then(), so componentDidMount can continue, but the code specified in .then() is invoked after usrs() returns, if you need to do something that has to happen after usrs() is done.
GolezTrol
  • 114,394
  • 18
  • 182
  • 210
  • Could you please give more and simple deatails with my example code – Iqbal Jan Mar 06 '19 at 09:32
  • Could you please tell me in my case what is the caller function to be wait untill this.usrs(usrs); completely done. – Iqbal Jan Mar 06 '19 at 11:33
  • Sorry. With 'caller', I simply mean the function that calls the async function. I've added that, and the 3 options you have to the answer. – GolezTrol Mar 06 '19 at 11:36
  • Thank you for your answer, I am just confiused about, if we use await so componentDidMount will wait for that, so if there some functions have to be called after caller it also have to be wait until the caller gets finishe. also if we use without await and usrs() didnt finished so componentDidMount will not keep it alive and skeep it. – Iqbal Jan Mar 06 '19 at 12:22
8

We use await when we need to call and wait for async function or Promise
In your case when you call it without await inside your componentDidMount, your function will work but your componentDidMount will not wait for that function to completely finishes.
Also if you don't want to use await and you don't want to wait inside componentDidMount, but you want to get notified when your async function finishes, you can use .then instead. Because async functions returns Promise

Here is your componentDidMount with .then
Notice that in this example this.doSomethingElse will call before the this.usrs is complete, and you only will be notified inside .then about your this.usrs result when it finished:

componentDidMount(){
    this.usrs(usrs).then(() => {
        // Your functions completely finished
    })
    .catch(err => {
        // There was an error
    });

    this.doSomethingElse();
}
SiSa
  • 2,594
  • 1
  • 15
  • 33
  • Hi Sisa, I think your response is near to my question, could you please tell if I use .then() function it will work the same as await ? I mean it componentDidMount func will wait for the function completely finishes? – Iqbal Jan Mar 06 '19 at 11:31
  • @Muhammad No, `componentDidMount` will not wait, instead you will be notified inside `.then` – SiSa Mar 06 '19 at 11:40
  • If we dont use await and componentDidMout will not be wait to that until get finishes. So what will happen if componentDidMout will not be wait? 1. My async function will not execute 2. My async function will execute after componentDidmout function – Iqbal Jan Mar 06 '19 at 14:26
  • @Muhammad When you do not use `await`, your async function will run in background and your `componentDidMount` will continue process without waiting for async – SiSa Mar 06 '19 at 14:33
4

The async work before the name of the function means that the function always returns a promise, so yes it is possible.

await makes JavaScript wait until the promise is resolved and it pauses when you need to work on the result of that promise.

To understand it better I recommend seeing following page https://javascript.info/async-await

Robert
  • 19,800
  • 5
  • 55
  • 85
2

You can call an async function from anywhere. Async function returns a promise so if you call it like below you can use it as if it was a Promise.

async function example(){
  return 10;
}
const returnOfAsync = example()
console.log(returnOfAsync instanceof Promise) // true
returnOfAsync.then((theReturn) => {
  console.log(theReturn) // 10
})
FabioCosta
  • 3,069
  • 6
  • 28
  • 50
1

Under the hood, an await is simply using a promise (same as a then()), the difference being that it waits for the promise to resolve before continuing execution of the code following it.

So...

Call an async function with await and you will receive the results of the async function after it has completed. Any code that follows the await will execute after the async call returns.

Call an async function without await and you will get a promise as the return value. Code following the await will execute immediately.

If the code that follows the async call requires the value returned from the async call or is dependent on something that happens in the async call, use await. If not, then don't.

Rodney P. Barbati
  • 1,883
  • 24
  • 18