Async Animation Frames Generator
Asynchronous generator function that executes a continuous stream of
user-supplied actions before the next repaint. Each time the browser is about to
repaint, the requestAnimationFrame()
callback is called, the promise resolves,
and the generator yields the timestamp of that frame.
This allows any code using this generator to synchronize with the browser's painting cycle, it can be especially useful for tasks like measuring frame rates, synchronizing animations, or performing time-based updates.
async function* animationFrames() {
while (true) {
yield await new Promise(globalThis.requestAnimationFrame);
}
}
MDN docs: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestAnimationFrame
Example
async function logFPS() {
const startTime = performance.now();
let numberOfFrames = 0;
for await (const timestamp of animationFrames()) {
if (timestamp >= startTime + 1000) break;
numberOfFrames++;
}
console.log("Frames Per Second: ", numberOfFrames);
}
logFPS();
When used in an asynchronous loop, animationFrames can help track how many
frames are rendered over a period of time. For example, in the run function
provided earlier, the for await
loop iterates over the frames produced,
allowing it to measure how many frames are rendered in one second.
Typewriter example
async function* typewriter(text, start = 0) {
let index = start;
for await (const timestamp of animationFrames()) {
if (index < text.length) {
const char = text[index];
index++;
yield char;
}
}
}
const text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
let value = "";
for await (const char of typewriter(text)) {
value += char;
document.body.innerHTML = value;
}