1

I am testing Async await in my angular application.

Here is the code:

import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  
  async main() {
    await this.one();
    await this.two();
    await this.three();
  }

  async one() {
    setTimeout(() => { 
      console.log('one finished');
    }, 5000);
  }

  async two() {
    setTimeout(() => { 
      console.log('two finished');
    }, 1000);
  }

  async three() {
    setTimeout(() => { 
      console.log('three finished');
    }, 4000);
  }

}

When I look into the console it's not appearing as intended.

It's appearing in order: two, three and one.

I need it to appear in order one, two and finally three.

How can I fix this?

Tomazbyden2000
  • 83
  • 3
  • 12
  • Your one, two and three don't await their respective timeout but return immediately. You must return a promise that resolves in the callback of the timeout – derpirscher Oct 28 '20 at 18:58
  • 1
    Does this answer your question? [How to control setTimeout with promises](https://stackoverflow.com/questions/64138772/how-to-control-settimeout-with-promises) – derpirscher Oct 28 '20 at 19:00

2 Answers2

2

This has nothing to do with Angular, this is how JavaScript works.

See this vanilla JS version:

class AppComponent  {
  async main() {
    await this.one();
    await this.two();
    await this.three();
  }

  async one() {
    setTimeout(() => { 
      console.log('one finished');
    }, 5000);
  }

  async two() {
    setTimeout(() => { 
      console.log('two finished');
    }, 1000);
  }

  async three() {
    setTimeout(() => { 
      console.log('three finished');
    }, 4000);
  }
}

let x = new AppComponent();
x.main();

I think you are expecting one() to take 5000 seconds, two() to take 1000 seconds and three() to take 4000 seconds to execute.

But Actually, they execute instantaneously, it set a timeOut and return the control flow to the caller.

Since console.logs are inside the timeOut functions, based on the timeout intervals.

You can create a setTimout function and await it on one(), two() and three()

async function setTimeouAsync(fn, ms) {
    return new Promise(resolve => {
        setTimeout(resolve, ms);
    }).then(() => {
        fn();
    });
}


@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  name = "Angular " + VERSION.major;

  async main() {
    await this.one();
    await this.two();
    await this.three();
  }

  async one() {
    await setTimeouAsync(() => {
      console.log("one finished");
    }, 5000);
  }

  async two() {
    await setTimeouAsync(() => {
      console.log("two finished");
    }, 1000);
  }

  async three() {
    await setTimeouAsync(() => {
      console.log("three finished");
    }, 4000);
  }

  constructor() {
    this.main();
  }
}

An example can be found HERE

B45i
  • 2,368
  • 2
  • 23
  • 33
0

setTimeout() does not return a Promise which you can await. You would need to do the following to make it work:

timeout(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async doSomething() {
  await timeout(5000);
  await timeout(1000);
  await timeout(3000);
}
Marek W
  • 699
  • 4
  • 14