Skip to content

promises.js

文件信息

  • 📄 原文件:01_promises.js
  • 🔤 语言:javascript

JavaScript Promise 本文件介绍 JavaScript 中的 Promise 异步编程。

完整代码

javascript
/**
 * ============================================================
 *                JavaScript Promise
 * ============================================================
 * 本文件介绍 JavaScript 中的 Promise 异步编程。
 * ============================================================
 */

console.log("=".repeat(60));
console.log("1. Promise 基础");
console.log("=".repeat(60));

// ============================================================
//                    1. Promise 基础
// ============================================================

/**
 * 【Promise 状态】
 * - pending:初始状态,等待中
 * - fulfilled:操作成功完成
 * - rejected:操作失败
 *
 * 状态一旦改变就不可逆
 */

// --- 创建 Promise ---
console.log("\n--- 创建 Promise ---");

const promise = new Promise((resolve, reject) => {
    // 模拟异步操作
    const success = true;

    setTimeout(() => {
        if (success) {
            resolve("操作成功");
        } else {
            reject(new Error("操作失败"));
        }
    }, 100);
});

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

promise
    .then(result => {
        console.log("成功:", result);
        return "处理后的结果";
    })
    .then(processed => {
        console.log("链式处理:", processed);
    })
    .catch(error => {
        console.log("错误:", error.message);
    })
    .finally(() => {
        console.log("无论成功失败都执行");
    });

// --- 快捷方法 ---
console.log("\n--- Promise.resolve / reject ---");

// 立即解决
Promise.resolve("立即解决的值")
    .then(value => console.log("resolve:", value));

// 立即拒绝
Promise.reject(new Error("立即拒绝"))
    .catch(err => console.log("reject:", err.message));


// 等待初始 Promise 完成
setTimeout(() => {
    console.log("\n" + "=".repeat(60));
    console.log("2. Promise 链式调用");
    console.log("=".repeat(60));

    // ============================================================
    //                    2. Promise 链式调用
    // ============================================================

    // --- 链式调用 ---
    console.log("\n--- 链式调用 ---");

    function step1(value) {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("Step 1 完成");
                resolve(value + 1);
            }, 100);
        });
    }

    function step2(value) {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("Step 2 完成");
                resolve(value * 2);
            }, 100);
        });
    }

    function step3(value) {
        return new Promise(resolve => {
            setTimeout(() => {
                console.log("Step 3 完成");
                resolve(value + 10);
            }, 100);
        });
    }

    step1(1)
        .then(step2)
        .then(step3)
        .then(result => {
            console.log("最终结果:", result);  // ((1+1)*2)+10 = 14

            // 继续执行后续代码
            runPart3();
        });

}, 500);


function runPart3() {
    console.log("\n" + "=".repeat(60));
    console.log("3. Promise 静态方法");
    console.log("=".repeat(60));

    // ============================================================
    //                    3. Promise 静态方法
    // ============================================================

    // 辅助函数
    const delay = (ms, value) =>
        new Promise(resolve => setTimeout(() => resolve(value), ms));

    const delayReject = (ms, error) =>
        new Promise((_, reject) => setTimeout(() => reject(new Error(error)), ms));

    // --- Promise.all ---
    console.log("\n--- Promise.all(全部成功)---");

    Promise.all([
        delay(100, "结果1"),
        delay(200, "结果2"),
        delay(150, "结果3")
    ])
        .then(results => {
            console.log("all 成功:", results);
        })
        .catch(error => {
            console.log("all 失败:", error.message);
        });

    // --- Promise.allSettled ---
    console.log("\n--- Promise.allSettled(不管成功失败)---");

    Promise.allSettled([
        delay(100, "成功1"),
        delayReject(150, "失败1"),
        delay(200, "成功2")
    ])
        .then(results => {
            console.log("allSettled 结果:");
            results.forEach((result, i) => {
                if (result.status === "fulfilled") {
                    console.log(`  ${i}: 成功 - ${result.value}`);
                } else {
                    console.log(`  ${i}: 失败 - ${result.reason.message}`);
                }
            });

            runPart4();
        });
}


function runPart4() {
    const delay = (ms, value) =>
        new Promise(resolve => setTimeout(() => resolve(value), ms));

    // --- Promise.race ---
    console.log("\n--- Promise.race(第一个完成)---");

    Promise.race([
        delay(300, "慢"),
        delay(100, "快"),
        delay(200, "中")
    ])
        .then(result => {
            console.log("race 胜出:", result);
        });

    // --- Promise.any ---
    console.log("\n--- Promise.any(第一个成功)---");

    const delayReject = (ms, error) =>
        new Promise((_, reject) => setTimeout(() => reject(new Error(error)), ms));

    Promise.any([
        delayReject(100, "快速失败"),
        delay(200, "成功"),
        delayReject(150, "另一个失败")
    ])
        .then(result => {
            console.log("any 成功:", result);
            runPart5();
        })
        .catch(error => {
            console.log("any 全部失败:", error);
        });
}


function runPart5() {
    console.log("\n" + "=".repeat(60));
    console.log("4. 错误处理");
    console.log("=".repeat(60));

    // ============================================================
    //                    4. 错误处理
    // ============================================================

    // --- catch 位置 ---
    console.log("\n--- 错误传播 ---");

    Promise.resolve()
        .then(() => {
            throw new Error("第一步出错");
        })
        .then(() => {
            console.log("这不会执行");
        })
        .then(() => {
            console.log("这也不会执行");
        })
        .catch(error => {
            console.log("捕获错误:", error.message);
            return "恢复正常";  // 可以恢复
        })
        .then(value => {
            console.log("恢复后:", value);
        });

    // --- 未处理的拒绝 ---
    console.log("\n--- 未处理的拒绝 ---");
    console.log(`
    建议始终添加 .catch() 处理错误
    Node.js 可以监听 unhandledRejection 事件
    浏览器可以监听 unhandledrejection 事件
    `);

    setTimeout(() => {
        runPart6();
    }, 200);
}


function runPart6() {
    console.log("\n" + "=".repeat(60));
    console.log("5. 实际应用");
    console.log("=".repeat(60));

    // ============================================================
    //                    5. 实际应用
    // ============================================================

    // --- 模拟 fetch ---
    console.log("\n--- 模拟 API 请求 ---");

    function mockFetch(url) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                if (url.includes("error")) {
                    reject(new Error("Network error"));
                } else {
                    resolve({
                        ok: true,
                        json: () => Promise.resolve({
                            url,
                            data: "模拟数据"
                        })
                    });
                }
            }, 100);
        });
    }

    mockFetch("/api/users")
        .then(response => response.json())
        .then(data => {
            console.log("请求成功:", data);
        })
        .catch(error => {
            console.log("请求失败:", error.message);
        });

    // --- 并行请求 ---
    console.log("\n--- 并行请求 ---");

    Promise.all([
        mockFetch("/api/users"),
        mockFetch("/api/posts"),
        mockFetch("/api/comments")
    ])
        .then(responses => Promise.all(responses.map(r => r.json())))
        .then(([users, posts, comments]) => {
            console.log("并行请求完成:");
            console.log("  users:", users.url);
            console.log("  posts:", posts.url);
            console.log("  comments:", comments.url);
        });

    // --- 超时处理 ---
    console.log("\n--- 超时处理 ---");

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

    const slowRequest = new Promise(resolve =>
        setTimeout(() => resolve("慢请求完成"), 500)
    );

    withTimeout(slowRequest, 200)
        .then(result => console.log("超时测试成功:", result))
        .catch(error => console.log("超时测试失败:", error.message));

    // --- 重试逻辑 ---
    console.log("\n--- 重试逻辑 ---");

    function retry(fn, times, delay = 100) {
        return new Promise((resolve, reject) => {
            function attempt(n) {
                fn()
                    .then(resolve)
                    .catch(error => {
                        if (n === 0) {
                            reject(error);
                        } else {
                            console.log(`  重试剩余 ${n} 次...`);
                            setTimeout(() => attempt(n - 1), delay);
                        }
                    });
            }
            attempt(times);
        });
    }

    let attemptCount = 0;
    const unreliableOperation = () => {
        attemptCount++;
        return new Promise((resolve, reject) => {
            if (attemptCount < 3) {
                reject(new Error("暂时失败"));
            } else {
                resolve("终于成功了");
            }
        });
    };

    retry(unreliableOperation, 5, 50)
        .then(result => console.log("重试结果:", result))
        .catch(error => console.log("重试失败:", error.message));

    setTimeout(() => {
        console.log("\n【总结】");
        console.log(`
Promise 基础:
- new Promise((resolve, reject) => {})
- .then() 处理成功
- .catch() 处理失败
- .finally() 总是执行

静态方法:
- Promise.all() - 全部成功才成功
- Promise.allSettled() - 等待全部完成
- Promise.race() - 第一个完成
- Promise.any() - 第一个成功
- Promise.resolve() / reject() - 快速创建

最佳实践:
- 始终添加 .catch() 处理错误
- 使用 Promise.all 并行请求
- 添加超时和重试机制
`);
    }, 1000);
}

💬 讨论

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

基于 MIT 许可发布