Asynchronous JavaScript
- JS is single threaded --- i.e. two bits of script cannot run at the same time, they have to run one after another
- usually JS runs code sequentially in top-down order --- but sometimes there is code that runs (or must run) after something else happens and also not sequentially --- this is asynchronous programming
Callbacks
- we use callback functions to make sure a function won't run before a task is completed but will run right after it is completed
- they are passed as parameters to other functions
- can be named, anonymous, or an arrow function
// named const message = function () { console.log('This message is shown after 3 seconds'); } setTimeout(message, 3000); // anonymous setTimeout(function () { console.log('This message is shown after 3 seconds'); }, 3000); // arrow setTimeout(() => { console.log('This message is shown after 3 seconds'); }, 3000); - callbacks commonly used in event declarations --- e.g. a message that occurs when a button is clicked
Promises
- "Quick recap: in Javascript, a Promise is an object used as a proxy for a value not yet known. It’s called a Promise because it’s saying “I may not know what the value of the return is right now, but I promise to return it at some point, stored inside this thing”. In that way , instead of immediately returning the final value (which a synchronous method would do ), Promises allow you to use an asynchronous method, get the final value, and queue up “next steps” that you want to run on the eventually-returned value,..." source
- a promise is a special JavaScript object that links the 'producing code' and the 'consuming
code' together
- 'producing code' does something and takes time
- 'consuming code' wants the result of the 'producing code' once it's ready
- the 'producing code' takes whatever time it needs to produce the promised result, and the promise makes that result available to the 'consuming code' when it's ready
// constructor syntax
let promise = new Promise(function(resolve, reject) {
// executor (the producing code)
});- the function passed to
new Promiseis called the executor --- whennew Promiseis created it runs automatically --- it contains the producing code which should eventually produce the result - the
resolveandrejectare callbacks provided by JS --- our only code is within the executor - the promise object returned by the
new Promiseconstructor has these internal properties:- state: initially 'pending', then changes to either 'fulfilled' when
resolveis called or 'rejected' whenrejectis called - result: initially undefined, then changes to
valuewhenresolve(value)is called orerrorwhenreject(error)is called
- state: initially 'pending', then changes to either 'fulfilled' when
So the executor eventually moves the promise to one of these states:

- example of 'fulfilled promise':
let promise = new Promise(function (resolve, reject) { // after 1 second, signal that the job is done with the result 'done' setTimeout(() => resolve('done'), 1000); }); - example of 'rejected promise':
let promise = new Promise(function (resolve, reject) { // after 1 second, signal that the job is done with the result 'done' setTimeout(() => reject(new Error ('Whoops!')), 1000); }); - a promise that is either resolved or rejected is called 'settled' (as opposed to the initial state of 'pending')
- the executor should call only one ---
resolveorreject--- any state change is final (immutable) --- all further calls ofresolveandrejectare ignored resolve/rejectexpect only one argument (or none) and will ignore any additional arguments- usually an executor does something asynchronously and calls
resolve/rejectafter some time --- but we can call them immediately - the properties
stateandresultof the Promise are internal --- they can't be directly accessed --- we can use.then,.catch, and.finallyfor that
Consumers: then, catch, and finally
then
- the first argument of
.thenis a function that runs when the promise is resolved, and receives the result - the second argument is a function that runs when the promise is rejected, and receives the error
- syntax:
promise.then( function(result) { /* handle a successful result */ }, function(error) { /* handle an error*/ } );
catch
- if the promise is rejected, the return value passes through and
.thens and is picked up by thecatch