This is the seventh day of my participation in the August More text Challenge. For details, see: August More Text Challenge
A Promise is an object that represents the result of an asynchronous computation. This result may or may not be ready, and the Promise API is deliberately vague about this: Promise values cannot be obtained synchronously; Only when the value is ready can a Promise be required to call the callback function. If we are defining an asynchronous API but want it to be based on a Promise, ignore the callback parameter and return the Promise object instead. The caller can then register one or more callbacks on the Promise object to be called when the asynchronous computation is complete.
The use of Promise
With the advent of Promises, the core JavaScript language, Web browsers have begun implementing Promise-based apis. Let’s see how to use a utility function that returns Promise:
getJSON(url).then(jsonData= > {
// This is a callback function that will be called asynchronously when the parsed JSON value is available.
});
Copy the code
Think of the THEN () method as a callback registration method, such as the addEventListener() method, used to register event handlers in the client-side Java script. If the THEN () method of a Promise object is called multiple times, each of the functions you specify will be called when the Promise’s computation is complete.
However, unlike many event listeners, a Promise represents a single calculation, and each function registered with then() will be called only once. It is worth noting that the function passed to THEN () is called asynchronously, even though the asynchronous computation has completed by the time then() is called.
At the simple syntactic level, the then() method is a unique feature of promises, and its idiomatic use is to append.then() directly to a function call that returns a Promise, without the need to assign a Promise object to a variable.
It is also common practice to use verbs to name functions that return promises and functions that use Promise results. These idioms make the code especially easy to read:
// Suppose you have a function that displays user profiles
function displayUserProfile(profile) { /* Omit implementation */ }
// Here's how to use a function with a Promise.
// Note that this line of code reads like an English sentence:
getJSON("/api/user/profile").then(displayUserProfile);
Copy the code
Promise handling errors
For a Promise, we can do this by passing a second function to the then() method:
getJSON("/api/user/profile").then(displayUserProfile, handleProfileError);
Copy the code
Promise represents the future result of the asynchronous computation that occurs after the Promise object is created. Because the computation is performed after the Promise object has been returned to us, traditional computation cannot return a value or throw an exception that we can catch. The function passed to THEN () provides an alternative. When the synchronous computation completes normally, it simply returns the result to the caller. When the promise-based asynchronous computation completes normally, it passes its result to the function as the first argument to THEN ().
When an error occurs in a synchronous calculation, it throws an exception that is propagated up the call stack until there is a catch clause to handle it. When an asynchronous computation runs, its caller is no longer on the stack, so it is impossible to return an exception to the caller if there is a problem.
Instead, promise-based asynchronous computation passes the exception (usually as some kind of error object, although it’s not required) to the second function we passed to then(). So, in the code above, if getJSON() works properly, it passes the result to displayUserProfile(). If an error occurs (the user is not logged in, the server is down, the user’s Internet connection is down, the request times out, and so on), getJSON() passes the error object to handleProfileError().
In practice, it is rare that two functions are passed to then(). When dealing with promises, there is a better, more conventional way of dealing with errors. To understand it, first consider what happens if getJSON() completes normally, but an error occurs in displayUserProfile(). When getJSON() returns, the callback function is called asynchronously, so it is also asynchronous and cannot meaningfully throw an exception (because there is no code on the call stack to handle it).
The usual way to handle errors in this code is as follows:
getJSON("/api/user/profile").then(displayUserProfile).catch(handleProfileError);
Copy the code
Using this code, the normal result of getJSON() will still be passed to displayUserProfile(), But any errors in getJSON() or displayUserProfile() (including any exceptions raised by displayUserProfile) are passed to handleProfileError(). The catch() method equals a shortened form of calling then(), equivalent to taking null as the first argument and specifying an error handler function as the second argument.