Promise in Javascript
In the previous post, we talked about callbacks in javascript and why they are needed.
The promise-based syntax provides a more readable approach of handling asynchronous functions in javascript. With Promise, we can execute our asynchronous functions in the appropriate order with robust error handling functionality.
How Promise works?
Applying promise to our previous post on callback we have the following
1const delay = (seconds) => new Promise((resolve, reject) => {2 setTimeout(() => {3 console.log(`executing delay ${seconds} seconds`)4 resolve(seconds)}, seconds*1000)5 })67console.log('before delay!!')8delay(2)9delay(3)10delay(6)11.then(12(res) => console.log(`this delay is done at ${res}`),13(rej) => console.log(`the error caught is ${rej}`))14.catch(err => console.log(err))
if you copy the above code to any javascript environment and run you’ll have the following output
1before the delay!!2Promise { <pending> }3executing delay 2 seconds4executing delay 3 seconds5executing delay 6 seconds6this delay is done at 6
What happened in the code above :smiley:
The above code executes a 2seconds delay first, then by 3seconds and lastly, 6seconds then prints out the appropriate response.
How Did we use Promise
First we made the delay function to return a promise as follows
1const delay = (seconds) => new Promise((resolve, reject) => {2 if(seconds > 5) return reject('seconds more than 5')3 setTimeout(() => {4 console.log(`executing delay ${seconds} seconds`)5 resolve(seconds)}, seconds*1000)6 })
Note: we added an if statement here to cause a promise rejection based on number of seconds as opposed from the initial code written
A Promise
is in one of these states:
- pending: initial state, neither fulfilled nor rejected.
- fulfilled: meaning that the operation completed successfully.
- rejected: meaning that the operation failed.
Note: A Promise takes two parameters which are 1. resolve: puts the promise in the fulfilled stage. 2. reject: puts the promise in the rejected stage.
From the above a delay function the promise is rejected
if the value of seconds is greater than 5 and is resolved
if the value of seconds is less than 6
How Did we execute the promise
We executed the promise in the following section
1console.log('before delay!!')2delay(2)3delay(3)4delay(6)5.then(6(res) => console.log(`this delay is done at ${res}`),7(rej) => console.log(`the error caught is ${rej}`))8.catch(err => console.log(err))
After a promise execute and its state is known i.e. fulfilled or rejected. We use the following to take further actions on the promise.
- Promise.then
- Promise.catch
- Promise.finally
Promise.then
In our case the then
function handle the last promise returned by delay(6)
.
The then
function receives two parameters the
i) promise response
i.e. the object/value returned by the promise
ii) promise error
i.e. the error returned by the promise if any
inside the .then
we can write a logic to handle such promise accordingly in our own case we simply printed to the console
1.then(2(res) => console.log(`this delay is done at ${res}`),3(rej) => console.log(`the error caught is ${rej}`))
:sunglasses:
Promise.catch
In .catch
method is used to handle all errors which have not been handled by the .then
function
In our case we do the following
1.catch(err => console.log(err))
Promise.finally
The .finally
method is used to perfom all house cleaning functions after the promise has been executed. it marks the end of the promise chain.
e.g. we can close an opened file which we opened during our promise execution here to release compute resources.
Promise chaining
Assume we have two delay functions which returns a promise
1const delay1 = (seconds) => new Promise((resolve, reject) => {2 if(seconds > 5) return reject('seconds more than 5')3 setTimeout(() => {4 console.log(`executing delay ${seconds} seconds`)5 resolve(seconds)}, seconds*1000)6 })789const delay2 = (seconds) => new Promise((resolve, reject) => {10 if(seconds > 5) return reject('seconds more than 5')11 setTimeout(() => {12 console.log(`executing delay ${seconds} seconds`)13 resolve(seconds)}, seconds*1000)14 })
We can chain the above promise exactly like this
1delay1(5) //returns 52.then(res => delay2(res)) //res=53.then(delay2) //also receives 5 as argument
The output is
1Promise { <pending> }2executing delay 5 seconds3executing delay 5 seconds4executing delay 5 seconds