re: Practical Ways to Write Better JavaScript VIEW POST

FULL DISCUSSION
 

While a lot of your advice is nice, about map and friends:

This directly communicates to the runtime, that the individual "iterations" have no connection or dependence to each other, allowing them to run concurrently.

No JS engine does this. JS doesn't magically run in parallel—it's a single-threaded language.

edit—I was a bit mean before. I blame lack of sleep.

 

From the article:

JS is single threaded, but not single-file (as in lines at school). Even though it isn't parallel, it's still concurrent. Sending an HTTP request may take seconds or even minutes, if JS stopped executing code until a response came back from the request, the language would be unusable.

I think you might have missed a couple paragraphs. In case this doesn't make sense, read my article about async, concurrency and parallelism.

 

Your article writes that map is a construct that JS provides us that runs tasks in parallel.

But map doesn't care if you're passing it an async function or not—it runs a function on everything you pass it, in order. Notably, even this is possible, because async functions don't yield unless you actually call await:

const x = [1,2,3,4,5];

let expectedValue = 1;

x.map(async (value) => {
  if (value !== expectedValue) {
    console.info('actual', value, 'expected', expected);
  }
  expectedValue++;
});

At some level you're right that map isn't an inherently parallel construct. But I still stand by what I said, map has the potential of being parallelized on a level that a traditional for-loop does not. A for-loop explicitly surfaces a mechanism to enforce ordering, a map (and forEach) do not.

In your example, the code is not guaranteed to have a consistent result. The only way it could be consistent is if V8 guaranteed in-order execution of asynchronous tasks, which it does not.

Another differentiator in my mind is state. Anyone who has worked with distributed systems, knows that shared state is incredibly expensive. A traditional for-loop inherently provides shared state, the iterator/bounds check variable i. This inherently orders the loop, while map may be implemented as ordered, it's an implementation detail. Original MapReduce wasn't ordered.

I would say the moment you slap await in there, the code is no longer asynchronous. It's blocking as any other line.

That’s not true. If I await a web request in some random function, it will still be asynchronous as long as the random function is invoked asynchronously.

Try doing two awaits in a row and check if they run concurrently. This is the definition of synchronous.

code of conduct - report abuse