Promise + .then() / .catch() 和 async/await详细使用教程

828 阅读3分钟

1. 基本的 Promise + .then() / .catch()

示例:Promise 基本用法

// 模拟一个异步操作的函数,返回一个 Promise
function fetchData(delay, result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            if (Math.random() > 0.5) { // 模拟成功和失败
                resolve(result);
            } else {
                reject("请求失败");
            }
        }, delay);
    });
}

// 使用 .then() 和 .catch() 处理 Promise
fetchData(1000, "数据1")
    .then((data) => {
        console.log("成功获取数据:", data);
        return fetchData(1000, "数据2"); // 返回一个新的 Promise
    })
    .then((data) => {
        console.log("成功获取数据:", data);
        return fetchData(1000, "数据3");
    })
    .then((data) => {
        console.log("成功获取数据:", data);
    })
    .catch((err) => {
        console.error("操作失败:", err);
    });

解释:

  1. .then() 用于处理成功的结果(即 resolve() 的返回值)。
  2. .catch() 用于捕获并处理异常(即 reject() 的错误)。

2. Promise + async/await

async/await 是基于 Promise 的语法糖,使异步代码的写法更加简洁和同步化。

示例:async/await 基本用法

// async/await 版本
async function fetchAllData() {
    try {
        const data1 = await fetchData(1000, "数据1");
        console.log("成功获取数据:", data1);

        const data2 = await fetchData(1000, "数据2");
        console.log("成功获取数据:", data2);

        const data3 = await fetchData(1000, "数据3");
        console.log("成功获取数据:", data3);
    } catch (err) {
        console.error("操作失败:", err);
    }
}

fetchAllData();

解释:

  1. async 标记一个函数为异步函数,该函数总是返回一个 Promise
  2. await 用于等待 Promise 完成并返回结果,语法看起来像是同步的。
  3. try/catch 结构用于捕获错误。

3. 串联操作 (Chaining)

串联操作是指多个异步操作按顺序执行,只有前一个操作成功后,才会执行下一个操作。

示例:Promise 串联操作(使用 .then()

function fetchDataWithDelay(delay, result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`成功获取数据: ${result}`);
            resolve(result);  // 模拟异步操作成功
        }, delay);
    });
}

// 使用 .then() 串联多个 Promise 操作
fetchDataWithDelay(1000, "数据1")
    .then((result) => fetchDataWithDelay(1000, "数据2"))
    .then((result) => fetchDataWithDelay(1000, "数据3"))
    .then((result) => console.log("所有数据都获取成功"))
    .catch((error) => console.error("发生错误:", error));

示例:async/await 串联操作

async function fetchDataSequentially() {
    try {
        await fetchDataWithDelay(1000, "数据1");
        await fetchDataWithDelay(1000, "数据2");
        await fetchDataWithDelay(1000, "数据3");
        console.log("所有数据都获取成功");
    } catch (error) {
        console.error("发生错误:", error);
    }
}

fetchDataSequentially();

解释:

  1. 串联:每个异步操作会按顺序执行,只有当前一个操作成功(resolve)后,才会执行下一个操作。
  2. .then()async/await 都可以用于串联多个异步操作。

4. 并行操作 (Parallel Execution)

并行操作是指多个异步操作同时执行,减少等待时间,适用于独立的异步任务。

示例:Promise 并行操作(使用 Promise.all()

function fetchDataWithDelay(delay, result) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`成功获取数据: ${result}`);
            resolve(result);  // 模拟异步操作成功
        }, delay);
    });
}

// 使用 Promise.all() 执行并行操作
Promise.all([
    fetchDataWithDelay(1000, "数据1"),
    fetchDataWithDelay(500, "数据2"),
    fetchDataWithDelay(1500, "数据3")
])
    .then((results) => {
        console.log("所有数据都获取成功:", results);
    })
    .catch((error) => {
        console.error("发生错误:", error);
    });

示例:async/await 并行操作

async function fetchDataInParallel() {
    try {
        const results = await Promise.all([
            fetchDataWithDelay(1000, "数据1"),
            fetchDataWithDelay(500, "数据2"),
            fetchDataWithDelay(1500, "数据3")
        ]);
        console.log("所有数据都获取成功:", results);
    } catch (error) {
        console.error("发生错误:", error);
    }
}

fetchDataInParallel();

解释:

  1. Promise.all() :将多个 Promise 放入一个数组,并行执行。当所有 Promise 都成功时,then() 会被触发;只要其中一个失败,catch() 会被触发。
  2. async/await 配合 Promise.all() 也可以执行并行操作,所有操作并行执行,直到它们都完成。

5. 串联 vs 并行

串联 (Sequential)

  • 每个异步操作必须等待前一个操作完成后才能执行。
  • 示例:下载多个文件时,必须按照顺序下载。

并行 (Parallel)

  • 所有异步操作可以同时开始,减少等待时间。
  • 示例:并发获取多个 API 数据,提高效率。

总结:

  • .then().catch() :通过链式调用来处理 Promise,适合处理按顺序执行的异步任务。
  • async/await:使代码看起来像同步操作,适合处理复杂的异步逻辑,代码更简洁。
  • 串联:当异步操作需要按顺序执行时使用。
  • 并行:当多个异步操作可以同时进行时使用 Promise.all()async/await 配合。