Welcome to Promises in Javascript Series 1. In this series, we’ll learn the basics of what a Promise is in Javascript, the why, and how you can use them.
Table of content
- What is a Promise in Javascript
- Why use promises in your code
- How to Create a Promise
- How to use a Promise
What is a Promise in Javascript
First of all, do not overthink the meaning of the term Promise
it’s exactly the same promise you know. You know how your mom promises to get you a new cartoon series if you come out with the best result, right?
Okay, I get it your mom must have promised you something else if you do something good.
That’ is the same thing we are going to do with Javascript.
A promise is a commitment to do something or to not do something.
That being said, a promise can only come back with either a rejection (your mom refused to give you what she promised for whatever reason) or a resolve (she delivered as promised whether you liked the gift or not 🤣 ).
Let’s see this in action with Javascript.
Assuming a user wants to log into your website and you present a login screen to them. That’s you making a promise to them that if they enter their username and password correctly you’ll log them in, otherwise, you’ll not let them in, right?
Let’s create a simulation for this scenario:
let’s say this is our server (the gatekeeper, you need to make him happy or get kicked)
const login = (username, password)=>{
if(username ==="peter" && password=="admin") return true
}
How to Create a Promise
Here is the gatekeeper saying, calm down. I am making you a promise, signed and sealed by the attorney in Promise constructor.
const promise = new Promise ((resolve, reject )=>{
// Here you can tell the user, alright hold on, I am trying to confirm my promise
console.log("..loading")
if (login("peter", "peter")){
resolve({message: "Congratulations, you made it" })
}else {
reject(new Error( "Oops, so sorry. Please, try again"))
}
})
Good.
How to use a Promise
Let’s see what the gatekeeper (say an API) comes back with. To check this out, we chain the .then
, .catch
keywords to the promise as shown below.
The .then
function takes two parameters. The resolved (if our gatekeeper is happy with us) or the rejected (if they think we need to try harder to please them - that means there is an error) response.
promise.then((result)=>{
console.log(result) // "Congratulations, you made it";
},
(error)=>{
console.log(error.message) // "Oops, so sorry. Please, try again";
})
So you can do whatever you want to do in the then function. Like the gatekeeper can send you to their dashboard, show you some nice stuff, allow you to eat any kind of food you like and all.
So, you see the other parameters (the error callback) of the .then
function? It works exactly the same way as the .catch
function. You can decide to use the .catch
function and leave out the other error call back function. That way our function will now look like this
promise
.then((result)=>{
console.log(result) // "Congratulations, you made it";
}})
.catch((error)=>{
console.log(error.message) // "Oops, so sorry. Please, try again";
})
Also, remember we had a “..loading” animation showing to the user when they were trying to log in, you can use .finally
block to stop it when the promise is settled, regardless of whether it was rejected or resolved.
You can attach as many .then
functions as possible and they will be executed according to the order to which you add them. This is one reason I love to use promises to avoid callback hell (you will see some more details about this further down this article)
The .finally
is also a good place to run some cleanup operations.
Why use a promise, you asked?
Hey there, one reason I would use a promise is that it’s easy to read and allows you to write maintainable code.
Another reason is to avoid a callback hell. To avoid writing callbacks that will end up like this:
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
Messy, right?
Well, the truth is if you write your call back properly you might not find yourself within the callback hell.
Callback hell comes as a result of bad code. But there are times where you have no option than to just write that hella code because you can’t figure out a better way yet. Well, you just decided to create another problem you will solve at a later date.
While you should get better at writing callbacks as it’s an important part of writing code with Javascript I enjoy using promises as it’s also based on callbacks.
Do you want to learn more about call back hell? Read this article at callbackhell.com
So, congratulations, you’ve come to the end of this series. Make sure you fulfill your promises.
Our next series will be on running multiple promises at once.
Cheers,
Stay safe.