I have been creating a service which recursively calculates the size of a folder on a filesystem. This involves summing the sizes of all files in the folder and then recursively summing the size of all subfolders using await
and Promise.all
. However I had a bug where the sizes of folders were not being summed but were overwriting each other, and after a lot of debugging I found it was caused by the behaviour of +=
.
Consider the following example:
const waitAndReturn = async (x, timeout) => new Promise(resolve => setTimeout(resolve, timeout, x));
let plusEqualsSum = 0;
let alternativeSum = 0;
const plusEqualsIsWeird = async () => {
const vals = [10, 5];
await Promise.all(vals.map(async val => {
plusEqualsSum += await waitAndReturn(val, 100);
console.log(`plusEqualsSum += ${val}: ${plusEqualsSum}`)
alternativeSum = await waitAndReturn(val, 100) + alternativeSum;
console.log(`alternativeSum = ${val} + alternativeSum: ${alternativeSum}`)
}));
console.log(`Final plusEqualsSum: ${plusEqualsSum}`);
console.log(`Final alternativeSum: ${alternativeSum}`);
};
plusEqualsIsWeird();
As we all know, x += y
is equivalent to x = x + y
; but when used with an async
call, i.e. x += await y
, the value of x
at the time of the call is used rather than the value of x after the await
. This causes a race condition when used in the above context, and seems unintuitive.
I am aware that x += y
is equivalent to x = x + y
, but argue that with the introduction of async
/await
it should be changed to x = y + x
to avoid bugs like this. This would not change its behaviour when used in conjunction with synchronous values, but would be much clearer when used with async
ones.
I am fairly new to JS so may either be doing something wrong or may have a poor philosophy on how x += y
should behave, but the current behaviour seems really unintuitive to me.
What are your thoughts?
Aucun commentaire:
Enregistrer un commentaire