Event
Load script
setTimeout
Mutation Obs.
queueMicrotask
render
render
render
Resolve Promise
MacroTask
MicroTask
Tick 1
Tick 2
Tick 3
// If these functions have asnyc components they will not work
const result1 = apiCall1();
// result1 won't be back yet, so it will be undefined
console.log(result1)
// What if instead of passing a result we passed a function to apiCall1
// to run when it had a result
function callback(result1){
console.log(result1)
}
// Now when the call is finished apiCall1 can pass the result to the callback
apiCall1(callback);
Hmmmm. Maybe not...
Callback Hell -->
api1Call() // executing this returns a promise, that's why we can .then()
.then(result1 => {
console.log('result1', result1);
// api2Call also returns a promise, that's why we can .then() again
return api2Call(result1); // <-- the result of this call
})
.then(result2 /* ends up here */ => {
console.log('result2', result2);
})
.catch(function(err){
console.log(err)
})
.finally(function(){
// ...
});
See 'States and Fates'
A Promise
is in one of these states:
pending: initial state, neither fulfilled nor rejected.
settled
.then() or .catch() put callback functions into an array
The first callback given to a then will be passed the result of the promise fullfillment
The next then will receive whatever that first callback returned
Any errors and we go to catch
IF we return a promise, this is called a 'promise chain'
We do this when we want to use the result of running one async operation when we call another (as you saw earlier)
If you are returning promises DO NOT add thens and catches to them without understanding that that creates a different chain and can skip parts of the original chain. (Try to avoid it where possible)
See demo
// We can create a promise using the Promise constructor
// We pass it a function called the 'executor'
// The executor gets 2 callbacks, one to resolve and one to reject the result
const promise = new Promise(function(resolve, reject){
const result = somethingThatTakesALongTime();
if (/* happy with result */) {
resolve(result); //<-- goes to next thens
} else {
reject('Was bs mate...'); // <-- goes to catch as an error with message
}
});
// Later in the code
promise
.then(result => console.log(result))
.catch(console.log(err.message));
Promise.all()
- when you need all to succeed
Promise.allSettled()
- seeing the results of several calls
Promise.any()
- trying to get at least one success
Promise.race()
- trying to get at least one response
Promise.reject()
- create a rejected promisePromise.resolve()
- create a resolved promiseasync function(){
try {
const result1 = await asyncCall1();
// call 2 depends on result of call 1
const result2 = await asyncCall2(result1);
console.log('final result', result2);
} catch(err) {
// handle error
console.log('err', err);
}
}
Asynchronous JavaScript And XML (now JSON)
/* fetch('http://example.com/movies.json') */
fetch('http://example.com/movies.json', {
method: 'POST',
headers: {
"Content-Type": "application/json; charset=utf-8"
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(requestBody)
})
.then((response) => {
// Handle response codes here...
if(!response.ok) throw response;
return response.json();
})
.then((result) => {
console.log(result);
})
.catch((err) => {
console.log(err)
});
async function callAPI(requestBody) {
try {
const response = await fetch("http://example.com/movies.json", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8"
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(requestBody)
});
if (!response.ok) {
throw response;
}
const data = await response.json();
renderFn(data);
} catch (err) {
console.log(err);
}
}
async function callAPI() {
try {
const response = await fetch(
"https://carsapp2050.fly.dev/api/v1/cars/"
);
if (!response.ok) {
throw response;
}
const data = await response.json();
// Put the data into the UI
renderFn(data);
} catch (err) {
console.log(err);
// show the user that an error occurred
showError(err);
}
}
async function callAPI(newCarData /* or FormDataObject*/) {
try {
const response = await fetch(
"https://carsapp2050.fly.dev/api/v1/cars/", {
method: "POST",
headers: {
"Content-Type": "application/json; charset=utf-8" // <-- NECESSARY if sending data
// 'Content-Type': 'application/x-www-form-urlencoded',
},
body: JSON.stringify(newCarData),
// body: FormDataObject,
});
if (!response.ok) throw response;
const data = await response.json();
// Put the data into the UI
renderFn(data);
} catch (err) {
console.log(err);
// show the user that an error occurred
showError(err);
}
}
async function callAPI(id, changes) {
try {
const response = await fetch(
`https://carsapp2050.fly.dev/api/v1/cars/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json; charset=utf-8" // <-- NECESSARY if sending data
},
body: JSON.stringify(changes),
});
if (!response.ok) throw response;
const data = await response.json();
// Put the data into the UI
renderFn(data);
} catch (err) {
console.log(err);
// show the user that an error occurred
showError(err);
}
}
async function callAPI(id) {
try {
const response = await fetch(
`https://carsapp2050.fly.dev/api/v1/cars/${id}`, {
method: "DELETE",
});
if (!response.ok) throw response;
// update the UI
renderFn();
} catch (err) {
console.log(err);
// show the user that an error occurred
showError(err);
}
}