Turning Callbacks Into Promises
Last updated
Was this helpful?
Last updated
Was this helpful?
As an experienced JavaScript developer, you probably already have a whole bunch of asynchronous code that uses callbacks. To get quickly familiar with Promises, let's see how you would "Promisify" a legacy, callback-using function and use it in your application.
Side note: source files of all examples and instructions for how to execute, are located at:
As an example of an asynchronous function, let's use one that makes an HTTP call. In the past you probably used the popular request
package, with code that may have looked something like the following:
This code calls Google Books API to retrieve all books written by Martin Fowler. In order to rewrite the code with Promises, we need a request
method that is "promisified" i.e. uses promises instead of asynchronous callbacks. Such version of the request
package does actually exist: and we can quickly rewrite the above code as:
When promises support is already available you can just chain asynchronous calls with the .then
syntax, as showed earlier. However, it won't always be the case and when it is not, or when you want to promisify your own legacy code, we should know how to do it. It's actually quite straightforward. Let's see how we could promisify an http call by wrapping the corresponding function of the classic request
package, ourselves:
What just happened? Basically, for a function to be "then-able" (participate in then()-based async workflow) it must return a function with reject() and resolve() methods. The Promise class, in the example above, is such function. Our asynchronous functions return an instance of the Promise class, invoking resolve() or reject() based on the success or failure of its execution, as shown in the above example.
To conclude this chapter, let's extend our example code with additional logic: when we retrieve author's books we resolve with a different message based on their popularity and error-out if they are not a published author, at all:
This code, if successfully executed should return:
Please note: the order of the lines in the response may vary, since our lookups are asynchronous and parallelized.
or using :
Side note: in the last example we started using arrow functions syntax when function is an argument being passed to another function. Arrow functions don't just shorten the syntax, but they also do not bind their own: this
, arguments
, super
, or new.target
, which makes them great candidates for the use-case. In ES6 syntax it is very common to use arrow function syntax when function is acting as an argument. Further in this documentation we will use arrow-functions for anonymous functions everywhere, since they make code less error-prone and more readable. If you are new to arrow-functions, we recommended reviewing to them and Dmitri Pavlutin's blog post.
A lot of times, you will find already-"promisified" versions of the packages that you have previously used with callbacks. It has also become quite common to see packages which had been written with promises in mind, to begin with. Case in point is the module - isomorphic implementation for the native replacement of the XMLHttpRequest object, in modern browsers. Fetch API and the fetch module have supported promises from their inception.