Chaining promises

One thing that we haven't touched on so far, which is interesting to consider, is the fact that promises can be chained. This is especially useful to avoid code duplication.

In our Fetch example, we have called an API, checked the status code, retrieved the body and parsed it as JSON. Here's another way to implement the same functionality but in a more reusable manner:

function checkResponseStatus(response: Response): Promise<Response> { 
    if (response.status >= 200 && response.status < 300) { 
        return Promise.resolve(response); 
    } else { 
        return Promise.reject(new Error(response.statusText)); 
    } 
}

function toJSON(response: Response): Promise<Response> { return response.json(); }
const responsePromise: Promise<Response> = fetch('https://api.worldbank.org/v2/countries?format=json'); responsePromise .then(checkResponseStatus) .then(toJSON) .then((jsonContent: unknown) => { console.log("Response content: ", jsonContent); }) .catch((error: unknown) => { console.error("An error occurred while fetching the data: ",
error); });

This time, we've defined a function whose sole responsibility is to check whether the given response has a valid status; it uses the Promise.resolve(...​) and Promise.reject(...​) functions to return a promise and a result.

It is possible to wait for a set of promises to complete/resolve using Promise.all(...​).

We've also defined a simple function taking care of the .json() call, which also returns a promise. Our code handling the Promise response is now more concise and much clearer. Also, the functions that we have defined can be reused!

You can define a function that will be invoked whether a promise succeeds or fails using .finally(() ⇒ { ...​ });. This is now well supported by modern runtime environments. To be able to use this with TypeScript, you need to add es2018.promise to the lib array in tsconfig.json, as explained here: https://blog.mariusschulz.com/2018/11/27/using-promise-finally-in-typescript.

Chaining promises is really useful and will make your life easier. But we can do even better by leveraging async and await. Let's look at those next.