Every web developer should be able to handle asynchronous work with confidence. That's why you need to learn about javascript promises. So what is asynchronous?Any code that relies on unknowable finishing time is asynchronous. Javascript is single threaded meaning you can't execute two threads at same time.J avascript is in the same thread with lot of other browser activities like updating styles,handling user actions etc.Activity in one of the things delays other things.
Callbacks are the default javascript technique to handle asynchronous work.
- Function loadImage(src, parent, callbackfunc) {
- var img = document.createElement(‘img);
- img.src = src;
- img.onLoad = callbackfunc;
- parent.appendChild(img);
- }
Here the callbackfunc, which is function, is passed as a parameter to another function and this function is called at a later time when some conditions are met i.e img.onLoad here.What if this resulted in a javascript error before the callback? What if the network request resulted in an error?Should the callback function still be called then?.Assume we implemented an error handling method to handle the errors that should solve our problem for now. But what if the callback function is also a synchronous operation and you need something to happen after that?You have to pass another function with another callback.Eventually it will result in a dreadful situation of nested callbacks which is hard to debug. Promises comes to our rescue here.They are the recommended options here because they offer flexibility ,intuitive syntax and easy error handling.
How Do Promises Work?
Promise is an object that can be returned synchronously from an asynchronous function. It will be in one of the four states.
- Fulfilled-Action completed successfully
- Rejected-Operation relating to the promise failed
- Pending -Action neither completed nor rejected etc.
- Settled-A promise is settled if it's not pending.
There is a standard syntax to define promises.
- var Promise = new Promise(function(resolve, reject) {
-
- if (
- {
- resolve(‘Hurray’)
- }
- else {
- reject(Error(‘’Sorry it broke));
- }
- });
The promise constructor takes one argument, a callback function with two parameters ’resolve’ and ‘reject’.What you should remember is that call resolve(‘sucess_value’) when result is successful,when the result fails it calls reject(‘fail_value’).The ‘Error’ object is not a required object but using it will help you when debugging because they capture stack trace.
Now that we have a promise let's consume it ,
- Promise.then(function(result) {
- console.log(result);
- },
- catch (err) {
- console.log(err);
- });
We use then() and catch() function to interact with a promise. Both are optional -- you can add callback for success and failure only.The .then method receives the promise's eventual value, in the case of success. The .catch method receives an error value, in the case of failure.
Let's create a simple example for promise in code,
- isTicketAvailable = true;
- var bookTickets = new Promise(function(resolve, reject) {
- if (isTicketAvailable) {
- var flight = {
- airline: 'Emirates',
- time: 18
- };
- resolve(flight);
- } else {
- var reason = "No ticket available";
- reject("reason");
- }
- });
- We create a simple promise that we name bookTickets to book flight tickets if available
- We give condition that isTicketAvailable is true then the promise is in resolved state
- We also specify that if isTicketAvailable is false then the promise is in its reject state
Now lets' use that promise that we have created
- var checkTickets = bookTickets.then(function(response) {
- console.log(response);
- }).catch(function(err) {
- console.log(err.message);
- });
- After we call our promise bookTickets we want to take action depending whether it resolve or reject and we use .then() and .catch() to specify what actions to take.
- The argument response is the exact value you pass in your promise resolve(flight). That will be flight in our case
- We also pass a function into .catch that takes an argument err. This argument takes the return of a rejected promise and is the exact value reject(reason). That will be reason in our case.
Chaining Promises
then() can be chained to create additional async functions one after another
Let's say you have another promise named gotTickets to show some message if you get your ticket.
- var gotTickets = function(ticketDetails) {
- var msg = 'Booked tickets for ' + ticketDetails.airline + 'at ' + ticketDetails.time + '.0';
- return Promise.resolve(msg)
- };
Here we didn't write the reject since it's optional.
- var checkTickets = function() {
- bookTickets.then(gotTickets).then(function(response) {
- alert(response)
- }).catch(function(err) {
- alert(err.msg);
- });
- };
- We chained promises here.gotTickets can only be started after the bookTickets
Being able to chain thenables(any method or object that returns a .then) is an incredibly powerful technique for simplifying complex sequences of asynchronous work.
Promises Are Asynchronous
- var checkTickets = function() {
- console.log("before booking");
- bookTickets.then(gotTickets).then(function(response) {
- console.log(response)
- }).catch(function(err) {
- console.log(err.msg);
- });
- console.log("after booking");
- };
Expected output would be
before booking
Booked tickets for Emiratesat 18.0
after booking
But the actual output will be like
That's something we call asynchronous, the code will run without blocking or waiting for the result. Anything that need to wait for promise to proceed, you put that in .then.
As of now native promises are safe to use with almost all major browsers except Internet Explorer and Opera Mini.
This is a pretty basic explanation for javascript promises .If you'd like to learn more (you should because soon thenables are going to be used everywhere)Google has an excellent documentation on Javascript promises thatyou can refer at here.
Happy Coding.