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.
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.
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.
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.
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
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"