1

in angular 5 how can I execute For loop in synchronous way. I have so far the below code which doesnt wait until ExcecuteAsyncCode is completed.

let items = new Array<Item>();

for (let i = 0; i <= 10000; i += 1) {

    this.ExcecuteAsyncCode(i).then(
    res => {
        let result = res;
        return result;
    }).then(response => {
        let temp = response as Item[];
        temp.forEach((cta: Item) => {   
          items.push(cta);
        });
    });

    // THIS EXCECUTED BEFORE ExcecuteAsyncCode PROMISE COMPLETED
    if (items.length < i) {
        return;
    }
}

2 Answers 2

2

There is no way to wait synchronously for an async operation to complete, and you wouldn't want to do it even if you could as that would block the browser UI.

You can either chain together then calls or for a more synchronous look to the async code you can use async /await

interface Item{
    id:number
}
class Test{
    async ExecuteAsyncCode(i:number) {
        return [] as Item[]
    }
    async method() {
        let items = new Array<Item>();

        for (let i = 0; i <= 10000; i += 1) {

            let temp = await this.ExecuteAsyncCode(i);
            temp.forEach((cta: Item) => {
                items.push(cta);
            });

            if (items.length < i) {
                return;
            }

        }
    }
}

You can read more about async /await here for example, it's worth mentioning this is not exclusive to Typescript, Javascript is getting async await as well

Sign up to request clarification or add additional context in comments.

4 Comments

I can see your argument about blocking UI. Do you have any suggestion on how to rewrite the "for loop" provided that the api doesn't return the count of all items. I was hoping to use sync for loop so I can break the iteration when the count of the returned items is less than a step.
@Jim Why doesn't the async/await solution work for you ? Once you are in async territory you are pretty much stuck there
please check the comment above
@Jim control flow will work as expected with async/await. You can break out of the for as you normally would
1

EDIT : You cannot simply mix sync (for-loop) with async. This approach eliminate use of for-loop but should be able to resolve what you are trying to achieve from your question.

export class AppComponent {

  ngOnInit() {
    this.method();
  }

  i: number = 0;

  // let's say async will exit after this.i reached 5
  items = 5;//new Array<Item>(); 

  method() {
    this.asyncMethod().then((result) => {
      if (this.i > 10) return;

      if (result === 'exit') { // break the async recursive call
        return;
      }
      else {
        this.i += 1;
        this.method(); // do recursive call while this.i <= 10000 and items.length < this.i
      }
    });
  }

  asyncMethod() {
    return new Promise((resolve) => {
      let currLoop = new Promise((resolve, reject) => {
        // mimic async function using timeout
        // replace your async function here, don't forget to indicate resolve() when function is done
        setTimeout(() => {
          resolve();
        }, 3000);
      }).then(() => {
        // exit condition
        if (this.items < this.i) {
          resolve('exit');
        } else {
          resolve('done');
        }
      });
    });
  }
}

4 Comments

thank you for the effort, however your answer doesn't solve my issue at all. I do cannot wait until all promises are completed.
Oh I see. How about eliminate loop and do recursive call instead? You can still utilize promises with that. I have ready made snippet but can't post on comment.
Edited as above. Hope it helps!
I really liked the recursive method idea. In fact, the combination of async/await would be the acceptable solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.