Asynchronous JavaScript
March 12, 2018
Event Loop
JavaScript executes on a single main thread, but leverages an event loop to offload and manage tasks without blocking.
Example setTimeout
const callback = () => {console.log("hello");}setTimeout(callback, 1000);
sequenceDiagram
autonumber
CallStack->>EventTable: [Timeout] [Callback]
EventTable->>EventQueue: [Callback]
Note over EventTable: [Timeout] expires
loop CallStack.length === 0
EventQueue->>CallStack: [Callback]
end
Callbacks
Series
const task1 = () => {setTimeout(() => {console.log(3);task2();}, 1000);}const task2 = () => {setTimeout(() => {console.log(4);}, 2000);}console.log(1);task1();console.log(2);
Parallel
let tasks = 2;const sync = () => {tasks--;if (tasks === 0) {console.log(5);}}const task1 = () => {setTimeout(() => {console.log(3);sync();}, 1000);}const task2 = () => {setTimeout(() => {console.log(4);sync();}, 2000);}console.log(1);task1();task2();console.log(2);
Promises
Promises can be composed together more easily.
const task1 = () => {return new Promise((resolve, reject) => {setTimeout(() => {console.log(3);resolve();}, 1000);});}const task2 = () => {return new Promise((resolve, reject) => {setTimeout(() => {console.log(4);resolve();}, 2000);});}
Series
console.log(1);task1().then(() => {return task2();});console.log(2)
(async () => {console.log(1);console.log(2);await task1();await task2();})();
Parallel
const sync = () => {console.log(5);}console.log(1);Promise.all([task1(), task2()]).then(() => {sync();});console.log(2);
(async () => {console.log(1);console.log(2);await Promise.all([task1(), task2()]);sync();})()
Errors
const task = () => {return new Promise((resolve, reject) => {reject(new Error('oh no!'));});};task().catch(err => {console.error(err);});
(async function() {try {await task();} catch(err) {console.error(err);}})();