Synchronous vs AsynchronoussetTimeoutsetIntervalCallbacksPromisesCreating PromiseCreating Promise using setTimeout()Consuming Promises1. Chaining .then and .catch2. Using await inside asyncFetch APIUsing Fetchinit ObjectAxiosInterceptor in Axios
Synchronous vs Asynchronous
- Synchronous code means code that executes in a sequence and is blocking, asynchronous code is executed in parallel
- JavaScript is synchronous single-threaded language but we can use asynchronous code with the help of our environment and event loop
- Asynchronous programming means that time-consuming operations don’t have to bring everything else in our programs to a halt.
setTimeout
- This is an async function provided to us by the browser that takes in 2 arguments, first the callback function to execute and the second is the time duration in milliseconds
- This executes the function atleast after the given duration
- In the code example below,
setTimeout()executes at last even though the time we have provided is 0 milliseconds because the main stack is executed first and only then things from side stack are added
console.log("Hello"); setTimeout(() => console.log("Inside"), 0) console.log("Bye"); // Output "Hello" "Bye" "Inside"
setInterval
- Similar to
setTimeout, setInterval keeps running a function after the given duration
- We can clear
setIntervalusingclearInterval
Callbacks
And understanding callback hell
Promises
- Promises are objects that represent the eventual outcome of an asynchronous operation. A Promise object can be in one of three states: Pending, Fulfilled or Rejected
- The
Promiseconstructor method takes a function parameter called the executor function, which runs automatically when the constructor is called.
Creating Promise
- We can create a promise using the Promise constructor
- The Promise constructor method takes a function parameter called the executor function
- This promise randomly either resolves or rejects
- The value of promise variable will be Pending
const promise = new Promise((resolve, reject) => { // Creating random true or false const randBool = Boolean(Math.floor(Math.random() * 2)); if(randBool){ resolve('Hey response') } else { reject("Sorry something went wrong") } }) console.log(promise); // pending
Creating Promise using setTimeout()
- Let’s look at how we’ll be using setTimeout() to construct asynchronous promises
const returnPromiseFunction = () => { return new Promise((resolve, reject) => { setTimeout(( ) => {resolve('I resolved!')}, 1000); }); }; const prom = returnPromiseFunction();
Consuming Promises
- We can consume (use) a promise with 2 types of syntax
1. Chaining .then and .catch
- We can nest .then to a promise. The value of previous .then will be passed on to the next .then and so on. This is called
chaining
- Remember this is also possible
.then(onSuccessHandler, onErrorHandler)but is generally not recommended
- The .catch block runs in case of any error
- The .finally runs at the end no matter what happens. It’s good for cleanup tasks that we might want to run eventually
- This process of chaining promises together is called composition. Promises are designed with composition in mind!
promise .then(data => console.log(data)) .catch(error => console.error(error)) .finally(() => console.log("Executed"))
Using
Promise.allWhen done correctly, promise composition is a great way to handle situations where asynchronous operations depend on each other or execution order matters. What if we’re dealing with multiple promises, but we don’t care about the order? Let’s think in terms of cleaning again.
For us to consider our house clean, we need our clothes to dry, our trash bins emptied, and the dishwasher to run. We need all of these tasks to complete but not in any particular order. Furthermore, since they’re all getting done asynchronously, they can all be happening at the same time!
To maximize efficiency, we should use concurrency, multiple asynchronous operations happening together. We can do this with promises using the function
Promise.all().Promise.all() accepts an array of promises as its argument and returns a single promise. That single promise will settle in one of two ways:- If every promise in the argument array resolves, the single promise returned from
Promise.all()will resolve with an array containing the resolved value from each promise in the argument array.
- If any promise from the argument array rejects, the single promise returned from
Promise.all()will immediately reject with the reason that the promise rejected. This behavior is sometimes referred to as failing fast, since one inner promise failing will settle the outer promise, regardless of whether the other inner promises are complete.
let myPromises = Promise.all([returnsPromOne(), returnsPromTwo(), returnsPromThree()]); myPromises .then((arrayOfValues) => { console.log(arrayOfValues); }) .catch((rejectionReason) => { console.log(rejectionReason); });
2. Using await inside async
- This is a cleaner ES6 syntax for the .then chaining
- It basically does the same thing as .then but in a more cleaner and synchrnous looking code
- Await will wait for the code to finish executing before moving ahead
- The await keyword can only be used inside an async function (that’s the catch)
function async getData(){ const data = await promise(); }
Fetch API
Things to remember in an API request: things might go wrong and a request always takes some time, it's not instantaneous
- Fetch API is provided to us by the browser and also node. This is used to get some data from a network request
- There is also XHR (
XMLHttpRequest) that we can use to get some data in the browser but its use is now obselete insteadfetchis more modern and better
Using Fetch
- We have to pass the URL with fetch, we can also pass additional parameters depending on our request
- Most common get request can be made using this code block
fetch(URL) .then(res => res.json()) .then(data => data) .catch(err => console.error("Something went wrong", err)) .finally(() => "Request complete")
- We have to parse our response using
res.json()as the response is a readable stream and we need to convert it to JS before using it
init Object
- Fetch also accepts another optional parameter called init which takes in more information
- This can be used to make all types of requests such as POST or DELETE and also settings headers
Axios
- It is an npm package that provides more cleaner way of making network requests
- It is cross-environment meaning that we can use it for browser as well as node
- It is more cleaner as compared to the normal fetch
Interceptor in Axios
- It allows us to use modify a request or response