Synchronous vs Asynchronous Code
Synchronous
: Means there is an inherent order among the commands and this order of execution is guaranteed.
Asynchronous
: No guarantee in the total order that commands are executed.
setTimeout()
: a method used to execute a callback after a given amount of time.
setInterval()
: Method that will continually execute a callback after a number of milliseconds, repeatedly.Can’t believe it’s async?
We cannot treat setTimeout as async under any circumstance.
The reason is that the time argument is not exact, it is the minimum amout of time
that will elapse before executing the callback.
Why do we need asynchronous code?
The environment we run our programs is full of uncertainty.
Because we are never in full control of the circumstances, the only thing we can control is our actual input code.
In the above example, ‘drink
’ will print out before our foo()
function executes due to our setTimeout.
non-blocking
because they do not prevent code that follows their invocation from running.There are also an unlimited number of arguments you can provide.
function foo(food1, food2) {
console.log(food1 + " for breakfast");
console.log(food2 + " for lunch");
}
setTimeout(foo, 2000, "pancakes", "couscous");
Cancelling Timeouts
function foo() {
console.log("food");
}
const val = setTimeout(foo, 2000);
console.log(val);
clearTimeout(val);
If we run this, we get a special Timeout object - which is essentially useless except for being used as an argument to cancel an unexpired timeout.
clearTimeout()
: function used to cancel a setTimeout.
Running Intervals
setInterval
accepts the same arguments as setTimeout
: callback function, time, …additional args)function foo(food1, food2) {
console.log(food1 + " and " + food2 + "!");
}
setInterval(foo, 1000, "pancakes", "couscous");
clearInterrval()
to cancel.Runtime
: term used to describe the ‘lifetime’ of a program.Single-threaded vs multi-threaded execution
Thread of execution
: term to describe a sequence of commands.Single-threaded execution
: Only one command can be processed at a time.
Multi-threaded
: Multiple commands can be processed at the same time.Keeping the Thread from Unraveling
Because JS is single-threaded if a user inititates part of our program while something else is being executed, they will have to wait.
This program will hang indefinitely because our timeout will never get to run.
Call Stack
: Structure that JS uses to keep track of the valuation of function calls - uses the stack
data structure.Stack
: General pattern of organizing a collection of items.
Stack Frames
: Term to describe the items that are being pushed and popped.The Practical Consequences of the Call Stack
A program will typically exit once it’s call stack is empty, the cases in which it does not is when it is Asynchronously Listening
.
An event can only be handled once the call stack is empty.
Javascript is the tool that enables web pages to be interactive and dynamic.
The Event Loop
Message Queue
: Keeps track of tasks that cannot be executed at the moment.The Message Queue
queue
data structure.Queue
: General patten of organizing a collection of things.Node’s readline module
Module
: A package of JS code that provides some useful functionality (i.e. Mocha for testing our code.)const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question("What's up, doc? ", (answer) => {
console.log("you responded: " + answer);
rl.close();
});
// try to print 'DONE!' after the question
console.log("DONE!");
The readline module is already pre-bundled with Node.
readline
: variable that is an object that contains all of the methods we can use from the module.createInterface
: Allows us to read and print information from the terminal.Question
: Method to ask the user something - accepts two arguments: a question message, and a callback.
Callback Chaining
rl.question("What's up, doc? ", (answer) => {
console.log("you responded: " + answer);
rl.close();
console.log("DONE!");
});
To avoid the issue of wonky async behavior we can simply put the command we want to follow at the end of the callback.
Callback Chaining
: Pattern than allows us to perform a series of async functions one after the other. (Take care to manage our code neatly, otherwise it can get messy!)
Example of messy code
// this code is a partial snippet from previous examples
rl.question("What's up, doc? ", (firstAnswer) => {
console.log(firstAnswer + " is up.");
rl.question("What's down, clown? ", (secondAnswer) => {
console.log(secondAnswer + " is down.");
rl.question("What's left, Jeff? ", (thirdAnswer) => {
console.log(thirdAnswer + " is left.");
rl.close();
});
});
});
callback hell
.How it looks after it has been refactored
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question("What's up, doc? ", handleResponseOne);
function handleResponseOne(firstAnswer) {
console.log(firstAnswer + " is up.");
rl.question("What's down, clown? ", handleResponseTwo);
}
function handleResponseTwo(secondAnswer) {
console.log(secondAnswer + " is down.");
rl.question("What's left, Jeff? ", handleResponseThree);
}
function handleResponseThree(thirdAnswer) {
console.log(thirdAnswer + " is left.");
rl.close();
}