2

My code looks like this:

someArray.forEach(x => {
// do something
console.log(‘calling api for ‘ + x);
callAnHttpApiAsync(...);
sleep(10);
});

The http api call is async (but I don’t use any await/async syntax) and logs something once the api sends back the response. What happens is that the forEach loop is completed and I start to see the logged responses ONLY AFTER that. I’d expect to see some responses before the loop is over (I tried increasing the amount of sleep), but no matter how long I wait or how long the loop is the responses are logged always after the loop is over. I use a sleep library of node. I see something like this:

calling api for 1
calling api for 2
calling api for 3
...
calling api for 10000
got response for 1
got response for 2
got response for 3
...
got response for 10000   

I solved already this issue by using for-of and await/async (please let me know if you have better ideas), but I can’t understand the reason of this weird behavior. Why do I get the responses only after the full loop? Any ideas? Sorry for the formatting but I’m on mobile.

8
  • 3
    it's async, what makes you think it will be waited for? Commented Apr 21, 2018 at 9:49
  • 2
    @AnuragSinghBisht — What? No. forEach is synchronous. If callAnApiAsync isn't then it makes no difference if it in a for or forEach loop. Commented Apr 21, 2018 at 9:51
  • 1
    Your solution is correct. At least I don't have a better idea. Using async/await with for loop will solve this problem. Commented Apr 21, 2018 at 9:51
  • 1
    @Quentin I meant that forEach will not wait for your async calls to complete. If you want async api's to complete and then run the next loop, you need to use the for loop. github.com/babel/babel/issues/909. Commented Apr 21, 2018 at 9:58
  • 1
    When you fire a synchronous job like forEach all other tasks, let them be synchronous or asynchronous has to wait up until it finishes. So that's what simply happening here. The sleep function as understand is synchrnous as mentioned in the NPM page These calls will block execution of all JavaScript by halting Node.js' event loop! so you are only slowing down your .forEach() and during that time nothing gets executed. Commented Apr 21, 2018 at 20:39

1 Answer 1

3

Full disclosure: I don't really know node.js, only client-side javascript, but I think the explanation works here as well.

The crux of the issue is that "asynchronous" doesn't mean "parallel". When you call an asynchronous operation, it gets placed in a queue. When the JSVM finishes executing the code it's currently running (which in this case is the code containing your forEach), then and only then does it take the first operation in the async queue and execute it; then, when that finishes, it runs the one after that, and so on. I.e. no matter how many async jobs you start, only one will ever run at a time.

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

Comments

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.