Created
July 3, 2018 12:20
-
-
Save zelaznik/d8bf76097990b42c8f5a0b424dce3f36 to your computer and use it in GitHub Desktop.
Javascript Event Loop Notes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Jake Archibald In The Loop: | |
Does this create cause the element to flash for a brief millisecond? | |
```js | |
document.body.appendChild(el); | |
el.style.display = none' | |
``` | |
No. There's no race condition. All this code takes place before a rendering is ever triggered. | |
<hr> | |
```js | |
button.addEventListener('click', event => { | |
while (true) { | |
//do nothing; | |
} | |
}); | |
``` | |
It freezes the animated git on the webpage. | |
https://youtu.be/cCOL7MC4Pl0?t=10m29s | |
<hr> | |
```js | |
function loop() { | |
setTimeout(loop, 0); | |
} | |
loop(); | |
``` | |
This does NOT block the rendering engine. The clock ticks many times before a single re-render. No need to refresh the screen every single microsecond. | |
## requestAnimationFrame | |
```js | |
function callback() { | |
moveBoxForwardOnePixel(); | |
requestAnimationFrame(callback); | |
} | |
``` | |
If we replace `requestAnimationFrame` with `setTimeout(..., 0)`, the box moves to the right about 3.5 times faster. | |
In Jake Archibald's tests, `setTimeout(() => {}, 0)` actually takes 4.7 ms. | |
Tasks happen in the order they're queued, but in terms of timing of a frame, no ordering at all. | |
Old animation libraries used this pattern: | |
```js | |
setTimeout(animFrame, 1000 / 60); | |
``` | |
If you use requestAnimationFrame, everything is neat and tidy, nice and ordered. | |
Try to move a block to the right and then transition to the center: | |
Attempt 001 (animates from 0 to 500): | |
```js | |
button.addEventListener('click', function() { | |
box.style.transform = 'translateX(1000px)'; | |
box.style.transition = 'transform 1s ease-in-out'; | |
box.style.transform = 'translateX(500px)'; | |
}); | |
``` | |
Attempt 002 (): | |
```js | |
button.addEventListener('click', function() { | |
box.style.transform = 'translateX(1000px)'; | |
box.style.transition = 'transform 1s ease-in-out'; | |
requestAnimationFrame(function() { | |
box.style.transform = 'translateX(500px)'; | |
}); | |
}); | |
``` | |
Final Attempt: | |
```js | |
button.addEventListener('click', function() { | |
box.style.transform = 'translateX(1000px)'; | |
box.style.transition = 'transform 1s ease-in-out'; | |
requestAnimationFrame(function() { | |
requestAnimationFrame(function() { | |
box.style.transform = 'translateX(500px)'; | |
}); | |
}); | |
}); | |
``` | |
You can use the web animation API, but that's limited to Chrome. | |
# Microtasks: | |
Strongly associated with Promises. | |
```js | |
(function loop() { | |
Promise.resolve().then(loop); | |
})(); | |
``` | |
Blocks the rendering. | |
https://youtu.be/cCOL7MC4Pl0?t=27m35s | |
Just because it's async doesn't mean it has to yield to rendering. It just has to yield to part of the event loop. | |
Tasks, Animation Callbacks, and Microtasks handle their queues differently. When a new item is pushed into the "Tasks" queue, it waits until the end of the line. Animation callbacks run to completion within a given animation frame, UNLESS a new animation callback is added during the rendering, in which case it's delayed until the next frame. Microtasks continue until its queue is empty. | |
### What order does the following take place: | |
```js | |
button.addEventListener('click', () => { | |
Promise.resolve().then(() => console.log('Microtask 1'); | |
console.log("Listener 1"); | |
}); | |
button.addEventListener('click', () => { | |
Promise.resolve().then(() => console.log('Microtask 2'); | |
console.log('Listener 2'); | |
}); | |
>>> "Listener 1" | |
>>> "Microtask 1" | |
>>> "Listener 2" | |
>>> "Microtask 2" | |
``` | |
https://youtu.be/cCOL7MC4Pl0?t=30m38s | |
### What if the button click is triggered by javascript? | |
```js | |
button.addEventListener('click', () => { | |
Promise.resolve().then(() => console.log('Microtask 1'); | |
console.log("Listener 1"); | |
}); | |
button.addEventListener('click', () => { | |
Promise.resolve().then(() => console.log('Microtask 2'); | |
console.log('Listener 2'); | |
}); | |
button.click(); | |
>>> "Listener 1" | |
>>> "Listener 2" | |
>>> "Microtask 1" | |
>>> "Microtask 2" | |
``` | |
https://youtu.be/cCOL7MC4Pl0?t=30m38s | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment