Skip to content

async await.js

文件信息

  • 📄 原文件:02_async_await.js
  • 🔤 语言:javascript

JavaScript async/await 本文件介绍 JavaScript 中的 async/await 语法。

完整代码

javascript
/**
 * ============================================================
 *                JavaScript async/await
 * ============================================================
 * 本文件介绍 JavaScript 中的 async/await 语法。
 * ============================================================
 */

console.log("=".repeat(60));
console.log("1. async/await 基础");
console.log("=".repeat(60));

// ============================================================
//                    1. async/await 基础
// ============================================================

/**
 * 【async/await 是 Promise 的语法糖】
 *
 * async 函数总是返回 Promise
 * await 等待 Promise 解决,暂停函数执行
 */

// --- async 函数 ---
console.log("\n--- async 函数 ---");

async function greet() {
    return "Hello, async!";  // 自动包装为 Promise
}

greet().then(msg => console.log("async 返回:", msg));

// 等同于
function greetPromise() {
    return Promise.resolve("Hello, Promise!");
}

// --- await ---
console.log("\n--- await 基础 ---");

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function fetchData() {
    console.log("开始获取数据...");
    await delay(100);  // 等待 100ms
    console.log("数据获取完成");
    return { id: 1, name: "Data" };
}

fetchData().then(data => console.log("获取到:", data));


// --- 顺序执行 ---
setTimeout(async () => {
    console.log("\n" + "=".repeat(60));
    console.log("2. 顺序执行与并行执行");
    console.log("=".repeat(60));

    // ============================================================
    //                    2. 顺序与并行
    // ============================================================

    const mockFetch = (name, time) => new Promise(resolve => {
        setTimeout(() => resolve(`${name} 完成`), time);
    });

    // --- 顺序执行 ---
    console.log("\n--- 顺序执行 ---");
    async function sequential() {
        console.log("顺序开始");
        const start = Date.now();

        const result1 = await mockFetch("请求1", 100);
        console.log("  ", result1);

        const result2 = await mockFetch("请求2", 100);
        console.log("  ", result2);

        const result3 = await mockFetch("请求3", 100);
        console.log("  ", result3);

        console.log(`顺序完成,耗时 ${Date.now() - start}ms`);
    }

    await sequential();

    // --- 并行执行 ---
    console.log("\n--- 并行执行 ---");
    async function parallel() {
        console.log("并行开始");
        const start = Date.now();

        // 同时发起所有请求
        const [result1, result2, result3] = await Promise.all([
            mockFetch("请求1", 100),
            mockFetch("请求2", 100),
            mockFetch("请求3", 100)
        ]);

        console.log("  ", result1, result2, result3);
        console.log(`并行完成,耗时 ${Date.now() - start}ms`);
    }

    await parallel();

    // --- 并发控制 ---
    console.log("\n--- 并发控制 ---");

    async function withConcurrencyLimit(tasks, limit) {
        const results = [];
        const executing = [];

        for (const task of tasks) {
            const p = Promise.resolve().then(task);
            results.push(p);

            if (limit <= tasks.length) {
                const e = p.then(() => executing.splice(executing.indexOf(e), 1));
                executing.push(e);

                if (executing.length >= limit) {
                    await Promise.race(executing);
                }
            }
        }

        return Promise.all(results);
    }

    const tasks = Array.from({ length: 5 }, (_, i) =>
        () => mockFetch(`任务${i + 1}`, 50)
    );

    const results = await withConcurrencyLimit(tasks, 2);
    console.log("并发控制结果:", results);

    runPart3();
}, 300);


async function runPart3() {
    console.log("\n" + "=".repeat(60));
    console.log("3. 错误处理");
    console.log("=".repeat(60));

    // ============================================================
    //                    3. 错误处理
    // ============================================================

    // --- try/catch ---
    console.log("\n--- try/catch ---");

    async function mightFail(shouldFail) {
        await new Promise(resolve => setTimeout(resolve, 50));
        if (shouldFail) {
            throw new Error("操作失败");
        }
        return "操作成功";
    }

    async function handleError() {
        try {
            const result = await mightFail(true);
            console.log(result);
        } catch (error) {
            console.log("捕获错误:", error.message);
        } finally {
            console.log("清理资源");
        }
    }

    await handleError();

    // --- 多个 await 的错误处理 ---
    console.log("\n--- 多个 await 错误处理 ---");

    async function multipleAwaits() {
        try {
            const a = await mightFail(false);
            console.log("步骤1:", a);

            const b = await mightFail(true);  // 这里会失败
            console.log("步骤2:", b);

            const c = await mightFail(false);  // 不会执行
            console.log("步骤3:", c);
        } catch (error) {
            console.log("捕获:", error.message);
        }
    }

    await multipleAwaits();

    // --- Promise.all 的错误处理 ---
    console.log("\n--- Promise.all 错误处理 ---");

    async function parallelWithError() {
        try {
            const results = await Promise.all([
                mightFail(false),
                mightFail(true),  // 失败
                mightFail(false)
            ]);
            console.log(results);
        } catch (error) {
            console.log("并行错误:", error.message);
        }
    }

    await parallelWithError();

    // --- 使用 allSettled 避免快速失败 ---
    console.log("\n--- Promise.allSettled ---");

    async function parallelNoFail() {
        const results = await Promise.allSettled([
            mightFail(false),
            mightFail(true),
            mightFail(false)
        ]);

        results.forEach((result, i) => {
            if (result.status === "fulfilled") {
                console.log(`  任务${i + 1}: ${result.value}`);
            } else {
                console.log(`  任务${i + 1}: 失败 - ${result.reason.message}`);
            }
        });
    }

    await parallelNoFail();

    runPart4();
}


async function runPart4() {
    console.log("\n" + "=".repeat(60));
    console.log("4. 实际应用模式");
    console.log("=".repeat(60));

    // ============================================================
    //                    4. 实际应用模式
    // ============================================================

    // --- 重试模式 ---
    console.log("\n--- 重试模式 ---");

    async function retry(fn, times, delayMs = 100) {
        for (let i = 0; i < times; i++) {
            try {
                return await fn();
            } catch (error) {
                console.log(`  尝试 ${i + 1}/${times} 失败`);
                if (i === times - 1) throw error;
                await new Promise(r => setTimeout(r, delayMs));
            }
        }
    }

    let attemptCount = 0;
    const unreliable = async () => {
        attemptCount++;
        if (attemptCount < 3) throw new Error("暂时失败");
        return "成功!";
    };

    try {
        const result = await retry(unreliable, 5);
        console.log("重试结果:", result);
    } catch (error) {
        console.log("重试失败:", error.message);
    }

    // --- 超时模式 ---
    console.log("\n--- 超时模式 ---");

    async function withTimeout(promise, ms) {
        const timeout = new Promise((_, reject) =>
            setTimeout(() => reject(new Error("超时")), ms)
        );
        return Promise.race([promise, timeout]);
    }

    const slowOp = new Promise(r => setTimeout(() => r("完成"), 500));

    try {
        const result = await withTimeout(slowOp, 100);
        console.log("超时测试:", result);
    } catch (error) {
        console.log("超时测试:", error.message);
    }

    // --- 队列模式 ---
    console.log("\n--- 队列模式 ---");

    class AsyncQueue {
        constructor() {
            this.queue = [];
            this.processing = false;
        }

        async add(task) {
            return new Promise((resolve, reject) => {
                this.queue.push({ task, resolve, reject });
                this.process();
            });
        }

        async process() {
            if (this.processing) return;
            this.processing = true;

            while (this.queue.length > 0) {
                const { task, resolve, reject } = this.queue.shift();
                try {
                    const result = await task();
                    resolve(result);
                } catch (error) {
                    reject(error);
                }
            }

            this.processing = false;
        }
    }

    const queue = new AsyncQueue();
    const delay = ms => new Promise(r => setTimeout(r, ms));

    queue.add(async () => { await delay(50); console.log("  任务1"); return 1; });
    queue.add(async () => { await delay(30); console.log("  任务2"); return 2; });
    queue.add(async () => { await delay(40); console.log("  任务3"); return 3; });

    await delay(200);

    // --- 取消模式(AbortController)---
    console.log("\n--- 取消模式 ---");

    async function cancellableOperation(signal) {
        for (let i = 0; i < 5; i++) {
            if (signal?.aborted) {
                throw new Error("操作已取消");
            }
            console.log(`  步骤 ${i + 1}`);
            await new Promise(r => setTimeout(r, 50));
        }
        return "完成";
    }

    const controller = new AbortController();

    // 100ms 后取消
    setTimeout(() => controller.abort(), 100);

    try {
        const result = await cancellableOperation(controller.signal);
        console.log(result);
    } catch (error) {
        console.log("取消:", error.message);
    }

    console.log("\n【总结】");
    console.log(`
async/await 核心:
- async 函数总是返回 Promise
- await 暂停执行直到 Promise 解决
- 使用 try/catch 处理错误

并行 vs 顺序:
- 顺序:逐个 await
- 并行:Promise.all([...])
- 部分失败:Promise.allSettled([...])

实用模式:
- 重试:循环 + try/catch
- 超时:Promise.race + setTimeout
- 取消:AbortController
- 并发限制:自定义控制逻辑

最佳实践:
- 总是处理错误(try/catch 或 .catch)
- 能并行就并行,提高性能
- 避免在循环中无意义的顺序 await
`);
}

💬 讨论

使用 GitHub 账号登录后即可参与讨论

基于 MIT 许可发布