Asynchronous operations entail race conditions provided they are evaluated in parellel. However, a counter should always be
evaluated in sequence as per logic. I'd claim this reveals another flaw of Javascript's Promise
type: It is actually a blend of
the two types (sequential) Task
and Parallel
. While the former is a monad the latter is only an applicative.
Bergi has a point, of course. Asynchronous operations in parallel should solely rely on immutable data. However, operations that are inherently sequential should be evaluated as such and thus it doesn't matter if the underlying data is immutable or not.
I am not that versed in dealing with promises, so I probably doesn't use the type correctly. However, it should be enough to illustrate my point.
let clock = 0;
const incSlowly = o => new Promise(res => {
if (clock == 12)
clock = 0; // reset
delay(1000, x => (o.value = x, res(x)), clock++);
});
const delay = (t, f, x) => {
return new Promise(res => setTimeout(y => res(f(y)), t, x));
};
<output id="out">0</output>
<button onclick="incSlowly(document.getElementById('out'))">Tick!</button>
It's important to remember that promises and
await
is basically sugar on top of callbacks. It does wonders for readability and code structure, but it's still callback hell underneath.