Skip to content

Instantly share code, notes, and snippets.

@zelaznik
Created July 3, 2018 12:20
Show Gist options
  • Save zelaznik/d8bf76097990b42c8f5a0b424dce3f36 to your computer and use it in GitHub Desktop.
Save zelaznik/d8bf76097990b42c8f5a0b424dce3f36 to your computer and use it in GitHub Desktop.
Javascript Event Loop Notes
# 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