while (true) {
task = taskQueue.pop();
execute(task);
}
What's a task?
What's a task queue?
How do tasks get in the task queue?
^
JavaScript, why are you like that?
JavaScript is single-threaded
- But remember, the JS engine is only one part of the browser
Browsers are multi-threaded
As well as running your JavaScript, a browser could be - keeping
track of mouse and keyboard events - making network requests -
handling timers - disk operations And any of these things could be
generating tasks, via callbacks
In fact, this idea is the very heart of the asynchronous programming
we all know and love so much
setTimeout(myCallbackFunction, 3000);
Hey WebAPIs! Could you wait 3 seconds and then run my callback
function?
No worries! You keep doing your thing, I'll take care of this.
while (true) {
task = taskQueue.pop();
execute(task);
}
So that's basically how tasks and task queues work. Of course, in
real life, it's a bit more complicated than that
The Rendering Pipeline
Long running tasks will cause your browser to start dropping frames
and, much like this cat, your app just won't run right
function repeat(reps, action) {
for (let i = 0; i < reps; i++) {
action();
}
}
function repeat(reps, action) {
action();
if (--reps) {
setTimeout(() => repeat(reps, action));
}
}
/* job.js */
onmessage = function(e) {
for (let i = 0; i < e.data.reps; i++) {
e.data.action();
}
}
/* app.js */
const worker = new Worker('job.js');
worker.postMessage(action, reps);
while (true) {
task = taskQueue.pop();
execute(task);
if (isRepaintTime()) repaint();
}
An event loop has one or more task queues.
bool did_work = delegate->DoWork();
if (!keep_running_)
break;
did_work |= delegate->DoDelayedWork(&delayed_work_time_);
if (!keep_running_)
break;
if (did_work)
continue;
did_work = delegate->DoIdleWork();
if (!keep_running_)
break;
Multiple task queues
Queues can be executed in any order
Tasks in the same queue must be executed in the order they
arrived
Tasks from the same source
must go in the same queue
while (true) {
queue = getNextQueue();
task = queue.pop();
execute(task);
if (isRepaintTime()) repaint();
}
Microtasks
A task that happens between a task and rendering
Between one task and the next, or between task and rendering
while (true) {
queue = getNextQueue();
task = queue.pop();
execute(task);
while (microtaskQueue.hasTasks())
doMicrotask();
if (isRepaintTime()) {
animationTasks = animationQueue.copyTasks();
for (task in animationTasks)
doAnimationTask(task);
repaint();
}
}
Don't block rendering
Promises beat tasks
Animate with requestAnimationFrame
console.error node_modules/react-dom/cjs/react-dom.development.js:530
Warning: An update to MyComponent inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://fb.me/react-wrap-tests-with-act
in MyComponent