JavaScript

How to Chain JavaScript Promises – Intro Tutorial to JavaScript Promises

What are JavaScript promises?

In it’s new ECMA 6 version, JavaScript allows you to create a new type of object called a Promise. Promises are used for asynchronous or deferred computations, and can be an alternative to the usual callback approach.

Promises can be used both on the browser (support is still not universal but it’s getting there) or in Node.js apps.

Promises can either resolve or get rejected. Inside of a promise, you are free to call the “resolve” and “reject” method whenever you see fit.

Example of a promise:

What’s wrong with using just callbacks?

Nothing, but there are times (specially on Node.js apps) when you are performing multiple operations and you need to wait for the result of one in order to move to the next. In these cases you enter what’s called the “callback hell”, when you have several callbacks inside of other callbacks.

For example, you need to do the following: read a MongoDB collection, call an external API, call some other API, save some data in MongoDB. In each step you need the result of the previous step. Using callbacks can make your code very messy.

This is an example when using JavaScript promises and chaining them together would make things easier

How do you chain JavaScript promises?

The following example shows how you can chain JavaScript native promises using the then keyword.

Imagine you have three methods that do asynchronous operations (example: Ajax calls, calls to API, Mongo operations, writing to disk, etc). You want to call “secondMethod” when “firstMethod” completes, and when “secondMethod” completes you then want to call “thirdMethod”.

See how easy this becomes with promises:

Learn JavaScript ES6 online at your own pace

Check out the online course Learn JavaScript ES6 on Zenva Academy for more information.

Published by

Pablo Farias Navarro

Pablo is a web + mobile app developer and entrepreneur. Pablo is the founder of ZENVA. Besides teaching online how to create games, apps and websites to over 85,000 students, Pablo has created content for companies such as Amazon and Intel.ZENVA runs four development communities featuring game, web and mobile app development tutorials: Zenva Academy, GameDev Academy, HTML5 Hive (also known as "the hive"), and for Spanish speakers, De Idea A App.Pablo holds a Master in Information Technology (Management) degree from the University of Queensland (Australia) and a Master of Science in Engineering degree from the Catholic University of Chile. Specialized in web, mobile application and game development.

Share this article

31
Leave a Reply

avatar
22 Comment threads
9 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
24 Comment authors
Diego R FGonz_laibaChrisroi sabahSavanna Meyers Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
алик
Guest

What does it mean “chain”? Is it executing parallel or one thing after another?

David Morcillo Muñoz
Guest
David Morcillo Muñoz

Promises are resolved sequentially so you can get a calculated value from one promise to the next :). If you are interested on a parallel execution I recommend you the async library https://github.com/caolan/async

David Morcillo Muñoz
Guest
David Morcillo Muñoz

Promises are resolved sequentially so you can get a calculated value from one promise to the next :). If you are interested on a parallel execution I recommend you the async library (https://github.com/caolan/async).

Ruan Rocha
Guest
Ruan Rocha

What if I want to pass an object between the chained functions?

xeno
Guest
xeno

How could I not see it? I guess my head was a bit confused about all the messy Promise tutorials out there. Yours is nice, clean and straight. Great article!

Matt Thomas
Guest
Matt Thomas

Nice, succinct example that took me far too long to find. This need to exemplified on high profile sites like https://expressjs.com/en/advanced/best-practice-performance.html#promises or https://www.promisejs.org/. Nice work!

Sonya Panich
Guest
Sonya Panich

I am a beginner, and am curious about how to add more methods to this chain. The confusion I am having right now is what to put into resolve, as well as where the someStuff is coming from. Thank you for your help!

Irgendwo
Guest
Irgendwo

Thank you for this great example. Finally I got it with your help. I struggled a little bit with promises until now. Just one doubt. How can I access after the promise-chain has completed the object data,newdata or result from your example?

I tried like this to get for example result from first promise:

firstMethod()
.then(secondMethod)
.then(
console.log(JSON.stringify(data, null, 4));
);

John Erb
Guest
John Erb

Pablo,
Thank you for the great article. I have been struggling with this for a long while and am not quite there yet.

What happens to the {result: someStuff.newData} in the thirdMethod’s resolve line?

How can I use that “result” in the rest of my program, outside of the chain?

Can I do something like resolve(someHigherScopeVar = {result: someStuff.newData});

Thanks, again.

Sharry
Guest

Agree with Matt Thomas. Spent 3 days looking for a Promise example that I understand – really helped me with my work. Thanks 🙂

fariazz
Guest
fariazz

Thanks for your comment, that’s great to hear! 🙂

xiwi
Guest
xiwi

What’s the improvement of $q in AngularJS if this works like a charm?
Buen tuto!

xiwi
Guest
xiwi

Same but I have to say that if you have to chain some $http this works better with Angular promises

Ramachandra jr
Guest
Ramachandra jr

I don’t get it where are the catch statements? or do I have to pass in a second function to then? maybe?

nitroceluloso
Guest
nitroceluloso

Thanks, i was trying to chain the promises and you explained quite simple.

William Yang
Guest
William Yang

var firstMethod = function() { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log(‘first method completed’); resolve({data: ‘123 from the first. ‘}); }, 2000); }); return promise; }; var secondMethod = function(someStuff) { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log(‘second method completed’); resolve({newData: (someStuff.data + ‘ some more data from the second.’)}); }, 2000); }); return promise; }; var thirdMethod = function(otherStuff) { var promise = new Promise(function(resolve, reject){ setTimeout(function() { console.log(‘third method completed’); resolve({result: otherStuff.newData+’ some more data from the third.’}); }, 2000); }); return promise; }; firstMethod() .then((value)=>{secondMethod(value) .then((value)=>{thirdMethod(value) .then((value)=>{console.log(value);}) })});

Tit
Guest
Tit

Thanks, finally a very clear example!

ChihebNabil
Guest
ChihebNabil

Great tutoriel ! i’m trying to solve the almost same problem can anyone help me ?
https://gist.github.com/chihebnabil/fa9e1b98e57779805ad380ce55cf7d83

Greg
Guest
Greg

The problem in this example is that there is no reusability. What if you had five items on a page that were calling to a server for data, but you had no way of knowing in what order the requests would be made? One of the big benefits of promises is that a subsequent request to a fulfilled promise will instantly return that fulfilled response, so after the first request receives the data, all of the subsequent requests would automatically receive that same data from that one server call. In this example, if the firstMethod were the XHR, there would… Read more »

Vijay Pawar
Guest
Vijay Pawar

awesome

djm
Guest
djm

Thanks for the great example that is particularly friendly to JavaScript noobs. So many other examples use => operators and other shorthand/shortcuts that make understanding the base concept more difficult. By separating out functions that return the Promises I finally got it. 🙂

Savanna Meyers
Guest
Savanna Meyers

How would you add catch functions into this chain if you wanted to catch errors for each promise?

roi sabah
Guest
roi sabah

roy = (num=0,promise=null) => {
return new Promise((resolve,reject)=>{
console.log(num,promise)
if(!num){
roy(num+1,promise);
}
else{
resolve(55);
return promise
}

})
}

roy().then(x=>{
console.log(‘x:’,x);
})

i get stuck allways with “pending”, why?

Chris
Guest
Chris

great example of promise chaining. Simple and to the point. Thank you very much!

_laiba
Guest
_laiba

please guide me a little bit… what if the previous then is returning a function so how can we resolve the then chain??? function handleEntityNotFound(res) { return function (entity) { if (!entity) { res.status(404).end(); return null; } return entity; }; } function saveUpdates(updates) { //console.log(updates); return function (entity) { var updated = _.merge(entity, updates); updated.save() .then(updated => { updated; }); }; } function respondWithResult(res, statusCode) { statusCode = statusCode || 200; return function (entity) { //console.log(entity); if (entity) { res.status(statusCode).json(entity); return null; } }; } Post.findById(req.params.id).exec() .then(handleEntityNotFound(res)) .then(saveUpdates(req.body)) .then(respondWithResult(res)) .catch(validationError(res)); }

Diego R FGonz
Guest
Diego R FGonz

If I send parameters the promises don’t execute in order, is there a workaround besides using global variables?