JS quiz: async function execution order
ฝัง
- เผยแพร่เมื่อ 23 พ.ค. 2018
- / javascript_operator_ca... - original Reddit discussion. The post has been deleted. No idea why.
• Jake Archibald on the ... - my event loop talk, which includes how microtasks work.
/ 999269332889763840 - Twitter quiz thread. - เกม
Thanks, it was very interesting!
But the code example in the end of the video shows bad usage of "map" function, I think it shouldn't be used to make side effects, instead you'd better use "map" to get array of sizes and then sum it up by calling "reduce".
You should do more talks. You are quite a brilliant speaker and presentor.
Thank you for the understandable explanation! I had the right hunch, but wasn't really sure about the suspension of the code. Gonna watch your talk about microtasks next, thanks for linking it!
Thanks for clarifying a way to avoid it at the end, very cool! So keep in mind what part of the code is async and syncronus. Nice :)
just amazing!
Thats a very good tip and great explanation, thanks for clarifying this !!!
i should try x = await 2 + x next time I'm on a computer.. i assume it would be 3 then.
it is!
Thank you! This is very interesting, I'll keep this in mind I'm sure I'm going to run into this :)
Dammit. I said 1 then 3. But it's so clear now.
Well. At least now I'll pay more attention to what happens when I use += and that sort of assignment operators. It's not as simple as it looks like...
Using "bluebird"'s Promise.reduce function, you can aggregate the sizes like that:
(async () => {
let getTotalSize = async (fileNames) => {
const totalSize = await Promise.reduce(fileNames, async function (accSize, fileName) {
let fileSize = await Promise.resolve(+fileName);
// getting the file size async
return accSize + fileSize;
}, 0);
return totalSize;
}
console.log(await getTotalSize(["1", "2", "3"]));
})();
This can even be reproduced without async/await or generators at all. Effectively this is what's happening:
```
x = 0
function foo () {
x = 10
return 2
}
x += foo()
```
Potentially dumb question... what if we change the order of the operands?
e.g. in the last example, totalSize = await getSize(file) + totalSize
Presumably it doesn't make a difference, but I'm wondering whether JS halts evaluation as soon as it finds a Promise.
UPDATE: I tested this and it DOES make a difference! Apparently JS DOES halt evaluation as soon as it finds a Promise. The output of the code below is 1 and 3.
let x = 0;
async function foo( ) {
x = await 2 + x;
console.log(x);
}
foo();
x += 1;
console.log(x)
Thanks for the video! Great explanation.
Could you tell me what software you're using for this interactive presentation and code highlighting?
I'm curious too.
It's a screencap of Chrome showing a little framework I threw together for slides. You can poke around the code at github.com/jakearchibald/preso, but it isn't really externally documented, so will be pretty frustrating to use. It's the same framework I use for my event loop talk linked in the description.
how did you make the animations ?
IA must learn this, because it keeps telling me that the result is 1 and then 3😂
try this: `totalSize = (await getSize(file)) + totalSize`
Yep, that works. Although, it might be something another person on the project swaps around because they think it does the same thing.
Am I the only who thought that 3 3 could be a possible outcome? I suck lol
totalSize = 0 + await getSize(file)
can this be fixed with following?
totalSize = 0 + (await getSize(file))
No, that would do the same thing
3:40 “This is going to be evaluated before any of the sizes return.” - I don’t get this. Doesn’t the async function run multiple times (for each element in the `files` array), and doesn’t the second iteration run after the `await` promise from the first iteration has resolved? So, no? When an iteration hits `await`, it pauses that iteration and starts the next one?
`Promise.all` takes an array of promises and evaluates them all in parallel. The `files.map` creates an array of promises, which then get run in parallel by `Promise.all`, which means they're all independent of each other.
“`files.map` creates an array of promises” - could you elaborate? It’s a `map`, and the callback function doesn’t return anything, so the result should be an array of `undefined` values, no?
`arr.map(callback)` will call `callback` for each item in `arr` synchronously. It doesn't switch to calling them async depending on what a given callback returns. To clarify: "doesn’t the second iteration run after the `await` promise from the first iteration has resolved?" no
Šime Vidas you're right, and now I'm confused too
Šime Vidas wanted to point out the same thing. The arrow function will return undefined, so the Promise.all will get an array of undefineds. May be a typo.
The main problem is still, that the callback for map is not pure. Returning the size and then summarizing it with reduce would be better.
How did you know to unravel '+=' in this situation? My intuition wouldn't have told me that.
I'm not sure where I learned that, but I believe it's just shorthand in most languages
Same with x++, ++x. Syntactic sugar, as Jake said. (Although those are slightly trickier.)
茴香豆的茴有几种写法
老哥, edge case 的讨论还是有必要的呀