Skip to content

Instantly share code, notes, and snippets.

@zelaznik
Last active July 3, 2018 16:47
Show Gist options
  • Save zelaznik/fd566bde4ad543faab6eeebc559924ed to your computer and use it in GitHub Desktop.
Save zelaznik/fd566bde4ad543faab6eeebc559924ed to your computer and use it in GitHub Desktop.

Jake Archibald In The Loop:

Does this create cause the element to flash for a brief millisecond?

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.


S-L-P

Style, Layout, Painting

button.addEventListener('click', event => {
  while (true) {
    //do nothing;
  }
});

It freezes the animated git on the webpage.

https://youtu.be/cCOL7MC4Pl0?t=10m29s


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

  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:

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):

button.addEventListener('click', function() {
  box.style.transform = 'translateX(1000px)';
  box.style.transition = 'transform 1s ease-in-out';
  box.style.transform = 'translateX(500px)';
});

Attempt 002 ():

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:

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.

(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:

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?

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