TypeScript Promise In-Depth

Promise is the foundation of JavaScript asynchronous programming, and TypeScript has full type support for Promise.

Through generic parameters, you can precisely specify the types of the Promise's resolved value and rejected value.


SVG Diagram: Promise Workflow Background Title Promise Workflow Creating a Promise Creating a Promise new Promise((resolve, reject) => {...}) Arrow pending Pending Branch: resolve/reject fulfilled ✓ rejected ✗ Bottom section: Methods then() · catch() · finally() Arrow marker

Why Promise?

In JavaScript, many operations are asynchronous, such as network requests, file reading, timers, etc.

Promise provides a unified asynchronous programming interface, making asynchronous code easier to write and manage.

TypeScript's generic support ensures the type safety of Promise.

Concept description:A Promise is an object that represents the final result of an asynchronous operation. It has three states: pending (in progress), fulfilled (succeeded), rejected (failed).


Creating a Promise

Use the Promise constructor to create a Promise, passing in an executor function.

Example

// Create a Promise, use a generic to specify the type of the resolved value
// Promise<string> means a string is returned on success
var promise = new Promise<string>(function(resolve, reject) {
    var success = true;
    if (success) {
        // Calling resolve means the operation succeeded; pass in the result value
        resolve("Success!");
    } else {
        // Calling reject means the operation failed; pass in the error
        reject(new Error("Failure"));
    }
});

// Use then to handle the success case
promise.then(function(value) {
    console.log("Done: " + value);
})["catch"](function(error) {
    // Use catch to handle the failure case
    console.log("Error: " + error.message);
});

Output:

Complete: Success!

Generics explanation:Promise<T>The T in Promise<T> is the type of the value when the Promise resolves successfully. This allows TypeScript to infer the type of the returned value.


Promise Chaining

The then and catch methods return a new Promise, allowing chained calls.

Example

// Chained call: each then returns a new value, which is received by the next then
var promise = Promise.resolve(1)
    .then(function(n) {
        // First then, n = 1
        return n * 2;  // Returns 2
    })
    .then(function(n) {
        // Second then, n = 2
        return n + 10;  // Returns 12
    })
    .then(function(n) {
        // Third then, n = 12
        console.log("Final result: " + n);
        return n;
    });

console.log("Promise chain: " + promise);

Output:

最终结果: 12
Promise 链: [object Promise]

Chaining:Each then returns a new Promise, allowing us to execute multiple asynchronous operations in sequence.


Promise.all

Promise.all waits for all Promises to complete and returns an array containing all results.

Example

// Create three Promises
var p1 = Promise.resolve(1);
var p2 = Promise.resolve(2);
var p3 = Promise.resolve(3);

// Promise.all waits for all Promises to complete
// Returns an array containing the results of all Promises
Promise.all([p1, p2, p3]).then(function(results) {
    console.log("All completed: " + results);
    // Calculate the sum
    console.log("Sum: " + results.reduce(function(a, b) { return a + b; }, 0));
});

Output:

全部完成: 1,2,3
总和: 6

Note:If any Promise fails, Promise.all will immediately reject and will not wait for other Promises to complete.


Promise.race

Promise.race returns the result of the Promise that completes first (whether successful or failed).

Example

// Create three Promises with different delays
var p1 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p1"); }, 100);
});
var p2 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p2"); }, 50);
});
var p3 = new Promise(function(resolve) {
    setTimeout(function() { resolve("p3"); }, 30);
});

// Promise.race returns the result of the first Promise to complete
Promise.race([p1, p2, p3]).then(function(value) {
    console.log("First to complete: " + value);
});

Output:

最先完成: p3

Use cases:Promise.race is often used to implement timeout functionality: racing a long-running Promise against a timeout Promise.


Promise.allSettled

Promise.allSettled waits for all Promises to settle (whether successful or failed) and returns the status and result of each Promise.

Example

// Create three Promises, one of which will fail
var p1 = Promise.resolve("Success");
var p2 = Promise.reject(new Error("Failure"));
var p3 = Promise.resolve("Done");

// Promise.allSettled waits for all Promises to settle
// Returns the status and value/reason of each Promise
Promise.allSettled([p1, p2, p3]).then(function(results) {
    results.forEach(function(result, index) {
        if (result.status === "fulfilled") {
            console.log("Promise " + index + ": " + result.value);
        } else {
            console.log("Promise " + index + ": " + result.reason.message);
        }
    });
});

Output:

Promise 0: 成功
Promise 1: 失败
Promise 2: 完成

Differences:Promise.all stops immediately on the first failure; Promise.allSettled waits for all Promises to settle.


Promise Type Annotations

TypeScript's generic support makes Promise type declarations precise.

Example

// Define a function that returns a Promise
// Promise<{ name: string; age: number }> specifies the type of the returned user object
function getUser(): Promise<{ name: string; age: number }> {
    return Promise.resolve({ name: "Alice", age: 25 });
}

// async function: implicitly returns a Promise
async function main() {
    // await automatically infers the type of user
    var user = await getUser();
    console.log("User: " + JSON.stringify(user));
}

main();

Type inference:TypeScript automatically infers the return type of a Promise based on generic parameters, giving us full type hints in async/await as well.


Notes

  • Generic parameters:Always specify generic parameters for Promise to clarify the return type
  • Error handling:Remember to use catch to handle Promise failures
  • all vs allSettled:Use allSettled when you need all results, and use all when you need fast failure.
  • async/await:Modern code recommends using async/await, as the syntax is more concise

Best practices:Prefer async/await syntax; it is still based on Promise, but reads like synchronous code.


Summary

Promise is the core of TypeScript asynchronous programming.

  • Promise:An asynchronous operation container with three states: pending/fulfilled/rejected
  • then/catch:Chaining to handle asynchronous results
  • Promise.all:Waits for all to complete; fails entirely if any one fails
  • Promise.race:Returns the first completed result
  • Promise.allSettled:Waits for all to settle and returns the status of each

Recommendation:Use async/await syntax with Promise to make asynchronous code both type-safe and easy to read.

x Other extensions