2.3 Promises
Promises are relatively new features designed to make implementing asynchronous programming easier. A Promise is a Javascript object that stores the result of an asynchronous operation.
Since the result of an asynchronous operation may not be available for some time, we cannot retrieve the result from a Promise at will. Instead, we request the Promise to call a callback once the result is available. For example:
//sumInt() is not a built-in function; and sumInt must return a promise sumInt(1000000000).then(displayResult);
Consider a hypothetical “sumInt” function that finds the sum of a bunch of integers asynchronously. If we use Promises to implement asynchronous programming, then the “sumInt” function would return a Promise. Promise objects have a then method. We pass our callback (“displayResult” in this case) to the then method. We invoke the “then” method on the Promise object returned from the “sumInt” function. Then, the “displayResult” callback function will be called, retrieving and displaying the result from our summation.
Some Promise Terminology
Before preceding, we should introduce some terminology to describe the success of our asynchronous operations with Promises. Promises in real-life are kept or broken. Similarly, Javascript Promises are “fulfilled” or “broken.” We call a Promise fulfilled when the first callback passed to then (the callback that displays the results of asynchronous computations) is called. We call a Promise rejected when the second callback passed to then (the callback that handles errors) is called. Other times, Promises can be “resolved.”
Creating Promise-Based Functions
Now, let’s take a closer look at how to implement Promise objects. In the example below, we have an asynchronous function “greet” that greets the user:
function greet(name) { return new Promise( (resolve, reject) => { if (name != undefined) resolve("Hello ${name}!"); else reject("Please provide name!"); }); } function ask(data) { return new Promise((resolve, reject) => { resolve("${data} how are you?"); }); } greet("Steve") .then(data => {return ask(data)}) .then(data => {console.log(data)}) .catch(e => {console.log(e)})
First, we pass a string name to the “greet” function. Then, we need to create a Promise object for our function to return. The promise constructor takes one function as its argument. That function expects two parameters - a resolution function and a rejection function, named resolve and reject by convention.
Notice the two static methods, “resolve” and “reject” (lines 4-8), in our promise constructor. These are built in methods; the “resolve” method resolves or fulfills the Promise, and the “reject” method rejects the Promise. “Resolve” takes a single argument and returns a Promise with that is fulfilled with that argument as value (or resolved, if the argument is a Promise). In the example above, the resolve method in the first Promise (lines 4-8) is fulfilled with the string “Hello ${name}”, if “name” has a defined value. Otherwise, the Promise gets rejected with the error message “please provide name”. Then, greet() returns our first Promise object.
We then call the “then” method on our first Promise object (line 19).
In the second then method call (line 20), we encounter another Promise-based function, ask(). Ask() returns a Promise. In its constructor (lines 12-14), we have a resolve function that fulfills the promise with the string “${data}, how are you doing?” as its value.
After, we call the third then method (line 21). This method gets passed a function that displays the value stored by the previous promise (the promise returned by the second then method).
Lastly, their is a catch clause to end the chain of then methods. It catches any errors that occur when running our code and displays an error message.
#Important: Errors in asynchronous operations, unlike in synchronous execution, are by default thrown away. So you should always add a catch clause in asynchronous code to catch errors. Otherwise, errors will go unreported!
Copyright © 2021 Code 4 Tomorrow. All rights reserved.
The code in this course is licensed under the MIT License.
If you would like to use content from any of our courses, you must obtain our explicit written permission and provide credit. Please contact classes@code4tomorrow.org for inquiries.