Every weekend, I like to travel different places. Two of my friends always help me to arrange weekend tours. Before every tour, I ask one of my friends to buy tickets. My friend promises me he will go and buy tickets for the tour. He creates a promise with me when he leaves.
If my friend can buy tickets, we will pack our things. If he can’t, we don’t need to pack. However, We can’t decide whether we need to pack or not until he calls us and confirm the news.
There could be three outcomes of the promise
- Pending – My friend went to buy the tickets, but he hasn’t confirmed us.
- Fulfilled – He was able to buy the tickets and confirmed us to pack.
- Rejected – He couldn’t buy the tickets, but confirmed us not to pack.
I inspired from Andy Shora’s blog to write a story about the promise.
Why do we need Promises in JavaScript?
Normally code is synchronise. One statement executes and there is a guarantee that next statement executes immediately afterwards. Threading on processors doesn’t necessarily guarantee that, however, the javaScript threading model ensures that all intents and purposes, javaScript runs in a single timeline.
Unlike synchronise code, Asynchronous code is not guaranteed to execute in a single unbroken timeline. In fact, We can’t assume when an asynchronous operation will complete. Even if we send first request first and second request second, we can’t assume that the first request will overturn sooner than the second. Network requests are one the common example of the asynchronous request. Any code relies on events or thread or just some kind of unknowable finishing time are asynchronous.
In summary, Asynchronous work happens at an unknown or unpredictable time. Promises are the best way to handle asynchronous code.
Callbacks vs Promises
Callbacks are the default way of handling asynchronous programming in JavaScript. Pass a function to another function then call the callback function at some time later when some conditions have been met.
However, there are few drawbacks of using callbacks. Such as
- Error handling
- Maintaining sequence of work.
- Difficult to debug.
So promises are the recommended options for asynchronous code. Because they can give us the flexibility, intuitive syntax, and easy error handling.
Promise terminology
A promise can be:
Fulfilled – The action relating to the promise succeeded
Rejected – The action relating to the promise failed
Pending – Hasn’t fulfilled or rejected yet
Syntax and Basic usage
We can create a promise by using the promise constructor.
new Promise(function(resolve, reject) {});
A new Promise is created with the new keyword and the promise provides resolve and reject functions to the provided callback. The basic syntax –
// From David Walsh’s JavaScript Promises API // https://davidwalsh.name/promises var p = new Promise(function(resolve, reject) { // Do an async task async task and then... if(/* good condition */) { resolve('Success!'); } else { reject('Failure!'); } }); p.then(function() { /* do something with the result */ }).catch(function() { /* error :( */ })
A simple example of using promise:
var p = new Promise(function(resolve, reject){ setTimeout(function () { resolve("complete after 2 seconds"); }, 2000); }); p.then(function(value) { console.log(value); });
Using promise on Ajax Request
A realistic example would be converting XMLHttpRequest to a promise-based task.
// From Jake Archibald's Promises and Back // http://www.html5rocks.com/en/tutorials/es6/promises/#toc-promisifying-xmlhttprequest function get(url) { // Return a new promise. return new Promise(function(resolve, reject) { // Do the usual XHR stuff var req = new XMLHttpRequest(); req.open('GET', url); req.onload = function() { // This is called even on 404 etc // so check the status if (req.status == 200) { // Resolve the promise with the response text resolve(req.response); } else { // Otherwise reject with the status text // which will hopefully be a meaningful error reject(Error(req.statusText)); } }; // Handle network errors req.onerror = function() { reject(Error("Network Error")); }; // Make the request req.send(); }); }
Now, we can use it
get('story.json').then(function(response) { console.log("Success!", response); }, function(error) { console.error("Failed!", error); });
Browser Support
There are already implementations of promises in browsers today. As of Chrome 32, Opera 19, Firefox 29, Safari 8 & Microsoft Edge, promises are enabled by default.
Further Reading
- JavaScript Promises – A to Z details about Native promises in JavaScript.
- JavaScript Promise API – Explained details of JavaScript Promise API.
- MDN – The Mozilla developer network has great documentation on promises.
Nice One
Nice Explanation!