Promises In Javascript

Quick Note: If you don’t understand anything or have any questions or just want to talk about tech, you can connect with me on Instagram, Facebook or twitter

Promises and Async Javascript

Important souces

  1. Source 1
  2. Source 2
  3. Source 3

Getting Started

Promises are basically to run synchronous code in our application. As, we know Javascript is asynchronous, hence promises actually end up adding lot of value when writing real world app.

Promise basically says that either the code (or say function) after execution will have a value or would throw error.

This is specially useful, In case of making request to external server of storing some data because such operations take time.

The most vague example of this can be explained by taking something as simple as this

function delay(t) {
return new Promise(function(resolve) {
return setTimeout(() => resolve("some value from promise"), t)
});
}

function logHi(text) {
console.log(text);
}
delay(1000).then(logHi)

In this example,

  • function delay is called.
  • Promise have resolve or reject
  • Promise is resolved it will run a timeout after 1000 and then return
  • afterwards logH1 function will be executed.

The code above uses a promise that we manually created because we wanted to resolve something after setTimeout which does not return a promise of it’s own. It essentially promisifies setTimeout. When you use a library like axios, it already returns a promise, so you can just use it like

axios.get(url).then((response) => )

There’s no need (and in fact it’s an anti-pattern) to wrap it in another new Promise. You can just take the promise returned from get() and call then() on that promise.

Understanding Promise Implementation

Consider this vaguely example

// an immediately resolved promise 
var p2 = Promise.resolve("foo");
// can get it after the fact, unlike events
p2.then((res) => console.log(res));
//This will log "foo"

While the above code works, we generally use promise this way

var p = new Promise((resolve, reject) => resolve(5));   p.then((val) => console.log(val)); // 5

Where promise is a constructor

Chaining Promises

One of the main benefits of Promises is that they allow us to chain asynchronous operations together. This means we can specify subsequent operations to start only when the previous operation has succeeded. This is called a Promise Chain

new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 2000);

}).then((result) => {
alert(result);
return result + 2;
}).then((result) => {
alert(result);
return result + 2;
}).then((result) => {
alert(result);
return result + 2;
});
  • Resolve and reject means promises are either resolved or rejected
  • PromiseStatus can have three different values.
  • Pending resolved or rejected
  • When promise is created Promise Status will be in the pending status and will have PromiseValue as undefined
  • Until the promise is either resolved or rejected

Understanding promises Object

var momsPromise = new Promise(function(resolve, reject) {
momsSavings = 20000;
priceOfPhone = 60000;
if (momsSavings > priceOfPhone) {
resolve({
brand: "iphone",
model: "6s"
});
} else {
reject("We donot have enough savings. Let us save some more money.");
}
});
momsPromise.then(function(value) {
console.log("Hurray I got this phone as a gift ", JSON.stringify(value));
});
momsPromise.catch(function(reason) {
console.log("Mom coudn't buy me the phone because ", reason);
});
momsPromise.finally(function() {
console.log(
"Irrespecitve of whether my mom can buy me a phone or not, I still love her"
);
});

.finally is declared for a promise then it will be executed whenever a promise is settled irrespective of whether it is fulfilled or rejected.

Promise.All

As per MDN documentation

The Promise.all(iterable) method returns a single Promise that resolves when all of the promises in the iterable argument have resolved or when the iterable argument contains no promises. It rejects with the reason of the first promise that rejects. Case 1 : When all the promises are resolved. This is the most frequently used scenario.

console.time("Promise.All");
var promisesArray = [];
promisesArray.push(promiseTRSANSG(1));
promisesArray.push(promiseTRSANSG(4));
promisesArray.push(promiseTRSANSG(2));
var handleAllPromises = Promise.all(promisesArray);
handleAllPromises.then(function(values) {
console.timeEnd("Promise.All");
console.log("All the promises are resolved", values);
});
handleAllPromises.catch(function(reason) {
console.log("One of the promises failed with the following reason", reason);
});

All promises resolved.

There are two important observations we need to make in general from the output.

  1. First : The third promise which takes 2 seconds finishes before the second promise which takes 4 seconds. But as you can see in the output, the order of the promises are maintained in the values.
  2. Second : I added a console timer to find out how long Promise.All takes. If the promises were executed in sequential it should have taken 1+4+2=7 seconds in total. But from our timer we saw that it only takes 4 seconds. This is a proof that all the promises were executed in parallel.

3.Case 2 : When there are no promises. I think this is the least frequently used.

console.time("Promise.All");
var promisesArray = [];
promisesArray.push(1);
promisesArray.push(4);
promisesArray.push(2);
var handleAllPromises = Promise.all(promisesArray);
handleAllPromises.then(function(values) {
console.timeEnd("Promise.All");
console.log("All the promises are resolved", values);
});
handleAllPromises.catch(function(reason) {
console.log("One of the promises failed with the following reason", reason);
});

Async and Await

async/await is a keyword+operator pair that simplifies asynchronous code.

*async declares the function is asynchronous.

  • await is the operator used to wait for a promise to be fulfilled. It can only be used within an async function.

Difference between Promise.all and async/await

Stackoverflow Question

  • Promise.all waits for resolving of every promise in parallel, on the other hand await does it one after the other, that being said if you had many different functions each heavily relying on the value from the previous one you could not use Promise.all in that scenario.
  • To use await, we need to nest it under Async function?
  • yes, await keyword is available only in async functions
  • Async solves the chaining problem?
  • it makes code looks more straightforward
  • but then so does Promise.all?

you still may use it with await, e.g.:

async function addAsync(x) {
const [a, b, c] = await Promise.all([
doubleAfter2Seconds(10),
doubleAfter2Seconds(20),
doubleAfter2Seconds(30)
]);
return x + a + b + c;
}

Un this case all promises inside Promise.all will be resolved in parallel and you will get results in 2 seconds, instead of 6

Using promise and async in NodeJS

app.get('/api/blogs', requireLogin, async (req, res) => {
const blogs = await Blog.find({ _user: req.user.id });
res.send(blogs);
});

Resolve Reject Promise

Source

const isGreater = (a, b) => {
return new Promise ((resolve, reject) => {
if(a > b) {
resolve(true)
} else {
reject(false)
}
})
}
isGreater(1, 2)
.then(result => {
console.log('greater')
})
.catch(result => {
console.log('smaller')
})

The ES6 Promises allows us to resolve and reject a request. Whenever we resolve a request it will call the callback provided in then and whenever we reject a request it will call the catch callback.

Further Reading

Understanding explicit promise construction anti pattern

If in case you are interested to connect with me or have any questions, here are my social profile Instagram, Facebook or twitter

Also don’t forgot to give a clap if you found this article useful