一般情况下,new Promise 应该传入两个参数。我不喜欢省略的模式。

在 Promise 构造函数中,确实通常会传入一个带有两个参数的回调函数,这两个参数分别是 resolve 和 reject。resolve 用于将 Promise 状态从 pending(进行中)变为 fulfilled(已成功),reject 则用于将其状态从 pending 变为 rejected(已失败)。

在之前给出的示例中,只使用了 resolve 而没有使用 reject,这是因为示例的目的是模拟一个只会成功不会失败的异步操作。不过在实际开发里,很多异步操作是可能会失败的,所以需要使用 reject 来处理错误情况。

下面是一个同时使用 resolve 和 reject 的示例:

javascript 复制代码
example.ts
Apply
function asyncOperationWithError(): Promise<void> {
    return new Promise((resolve, reject) => {
        // 模拟一个可能失败的异步操作,这里用 Math.random 来随机决定是否成功
        const randomNumber = Math.random();
        setTimeout(() => {
            if (randomNumber < 0.5) {
                console.log('异步操作成功');
                resolve();
            } else {
                console.log('异步操作失败');
                reject(new Error('异步操作失败'));
            }
        }, 2000);
    });
}

async function main() {
    console.log('开始异步操作');
    try {
        await asyncOperationWithError();
        console.log('异步操作已成功结束');
    } catch (error) {
        console.error('异步操作出错:', error);
    }
}

main();

代码解释

  1. asyncOperationWithError 函数:

    • 创建了一个 Promise,其回调函数接收 resolve 和 reject 两个参数。
    • 使用 Math.random() 生成一个 0 到 1 之间的随机数,如果这个数小于 0.5,就认为异步操作成功,调用 resolve();否则认为操作失败,调用 reject() 并传入一个 Error 对象。
  2. main 函数:

    • 这是一个异步函数,使用 try...catch 块来处理 asyncOperationWithError 可能抛出的错误。
    • 如果 asyncOperationWithError 成功(Promise 状态变为 fulfilled),则打印 异步操作已成功结束;如果失败(Promise 状态变为 rejected),则在 catch 块中捕获错误并打印错误信息。

所以,当你处理可能失败的异步操作时,通常要同时传入 resolve 和 reject 来分别处理成功和失败的情况。


以下是一个有返回值的 Promise 示例,在这个示例中,我们会模拟一个异步的数据库查询操作,该操作会返回查询到的数据。

javascript 复制代码
example.ts
Apply
// 模拟数据库查询,返回一个 Promise,该 Promise 会在 2 秒后返回查询结果
function queryDatabase(): Promise<string[]> {
    return new Promise((resolve, reject) => {
        // 模拟 2 秒的查询延迟
        setTimeout(() => {
            const success = Math.random() < 0.8;
            if (success) {
                // 模拟查询成功,返回一个字符串数组作为查询结果
                const result: string[] = ['data1', 'data2', 'data3'];
                resolve(result);
            } else {
                // 模拟查询失败,返回一个错误信息
                reject(new Error('数据库查询失败'));
            }
        }, 2000);
    });
}

// 调用数据库查询函数,并处理结果
async function main() {
    console.log('开始查询数据库');
    try {
        const data = await queryDatabase();
        console.log('查询成功,结果如下:', data);
    } catch (error) {
        console.error('查询出错:', error);
    }
}

// 启动主函数
main();

代码解释

  1. queryDatabase 函数:

    • 该函数返回类型为 Promise<string[]>,表示它会返回一个 Promise,当这个 Promise 成功解决时,会返回一个字符串数组。
    • 在 Promise 的回调函数中,使用 setTimeout 模拟 2 秒的查询延迟。
    • 通过 Math.random() < 0.8 来模拟查询成功的概率(80% 的成功率)。
    • 如果成功,使用 resolve(result) 将查询结果(一个字符串数组)传递出去;如果失败,使用 reject(new Error('数据库查询失败')) 抛出一个错误。**
  2. main 函数:

    • 这是一个异步函数,使用 await 关键字来等待 queryDatabase 函数返回的 Promise 被解决。
    • 使用 try...catch 块来处理可能出现的错误。如果查询成功,将查询结果打印到控制台;如果查询失败,捕获错误并打印错误信息。

通过这种方式,我们可以处理有返回值的异步操作,并对可能出现的错误进行捕获和处理。


以下是一个包含两个 Promise 嵌套,且第二个 Promise 接收第一个 Promise 结果的 TypeScript 示例:

typescript 复制代码
example.ts
Apply
// 第一个 Promise 函数,模拟异步获取用户 ID
function getUserID(): Promise<number> {
    return new Promise((resolve, reject) => {
        // 模拟异步操作,如网络请求
        setTimeout(() => {
            const success = Math.random() < 0.8;
            if (success) {
                // 模拟成功获取用户 ID
                const userID = 123;
                resolve(userID);
            } else {
                // 模拟获取失败
                reject(new Error('获取用户 ID 失败'));
            }
        }, 1500);
    });
}

// 第二个 Promise 函数,接收用户 ID 并模拟异步获取用户信息
function getUserInfo(userID: number): Promise<{ name: string; age: number }> {
    return new Promise((resolve, reject) => {
        // 模拟异步操作,如根据用户 ID 从数据库获取用户信息
        setTimeout(() => {
            const success = Math.random() < 0.8;
            if (success) {
                // 模拟成功获取用户信息
                const userInfo = { name: 'John Doe', age: 30 };
                resolve(userInfo);
            } else {
                // 模拟获取失败
                reject(new Error(`获取用户 ID 为 ${userID} 的信息失败`));
            }
        }, 1500);
    });
}

// 主函数,调用上述两个 Promise 函数
async function main() {
    try {
        console.log('开始获取用户 ID...');
        const userID = await getUserID();
        console.log(`成功获取用户 ID: ${userID},开始获取用户信息...`);
        const userInfo = await getUserInfo(userID);
        console.log('成功获取用户信息:', userInfo);
    } catch (error) {
        console.error('操作出错:', error);
    }
}

// 启动主函数
main();

代码解释:

  1. getUserID 函数:

    • 该函数返回一个 Promise<number>,表示会返回一个 Promise,当 Promise 成功时,会返回一个 number 类型的用户 ID。
    • 使用 setTimeout 模拟一个异步操作,有 80% 的概率成功获取用户 ID,若成功则调用 resolve 并传入用户 ID;若失败则调用 reject 并传入错误信息。
  2. getUserInfo 函数:

    • 该函数接收一个 number 类型的 userID 参数,返回一个 Promise<{ name: string; age: number }>,表示返回的 Promise 成功时会得到一个包含用户姓名和年龄的对象。
    • 同样使用 setTimeout 模拟异步操作,根据传入的 userID 去获取用户信息,有 80% 的概率成功,成功时调用 resolve 并传入用户信息对象,失败时调用 reject 并传入错误信息。
  3. main 函数:

    • 这是一个异步函数,使用 await 关键字来按顺序执行 getUserID 和 getUserInfo 函数。
    • 先调用 getUserID 函数获取用户 ID,若成功则接着使用该用户 ID 调用 getUserInfo 函数获取用户信息。
    • 使用 try...catch 块捕获可能出现的错误并打印错误信息。

通过这种方式,实现了两个 Promise 的嵌套,并且第二个 Promise 接收了第一个 Promise 的结果。

以下是使用老式的 Promise 链式调用方式(即将第二个 Promise 写在第一个 Promise 的 resolve 回调里)来实现相同功能的示例代码:

typescript 复制代码
example.ts
Apply
// 第一个 Promise 函数,模拟异步获取用户 ID
function getUserID(): Promise<number> {
    return new Promise((resolve, reject) => {
        // 模拟异步操作,如网络请求
        setTimeout(() => {
            const success = Math.random() < 0.8;
            if (success) {
                // 模拟成功获取用户 ID
                const userID = 123;
                resolve(userID);
            } else {
                // 模拟获取失败
                reject(new Error('获取用户 ID 失败'));
            }
        }, 1500);
    });
}

// 第二个 Promise 函数,接收用户 ID 并模拟异步获取用户信息
function getUserInfo(userID: number): Promise<{ name: string; age: number }> {
    return new Promise((resolve, reject) => {
        // 模拟异步操作,如根据用户 ID 从数据库获取用户信息
        setTimeout(() => {
            const success = Math.random() < 0.8;
            if (success) {
                // 模拟成功获取用户信息
                const userInfo = { name: 'John Doe', age: 30 };
                resolve(userInfo);
            } else {
                // 模拟获取失败
                reject(new Error(`获取用户 ID 为 ${userID} 的信息失败`));
            }
        }, 1500);
    });
}

// 主函数,调用上述两个 Promise 函数
function main() {
    getUserID()
      .then((userID) => {
            console.log(`成功获取用户 ID: ${userID},开始获取用户信息...`);
            return getUserInfo(userID);
        })
      .then((userInfo) => {
            console.log('成功获取用户信息:', userInfo);
        })
      .catch((error) => {
            console.error('操作出错:', error);
        });
}

// 启动主函数
main();

代码解释:

  1. getUserID 函数:

    • 此函数返回一个 Promise<number>,使用 setTimeout 模拟异步操作来获取用户 ID。以 80% 的概率成功获取用户 ID,成功时调用 resolve 并传入用户 ID,失败时调用 reject 并传入错误信息。
  2. getUserInfo 函数:

    • 该函数接收一个 number 类型的 userID 参数,返回一个 Promise<{ name: string; age: number }>。同样使用 setTimeout 模拟根据用户 ID 获取用户信息的异步操作,以 80% 的概率成功获取,成功时调用 resolve 并传入用户信息对象,失败时调用 reject 并传入错误信息。
  3. main 函数:

    • 调用 getUserID 函数,使用 .then 方法处理其返回的 Promise。
    • 在第一个 .then 回调中,接收 getUserID 成功返回的用户 ID,打印相应信息,然后调用 getUserInfo 函数并返回其返回的 Promise。
    • 第二个 .then 回调用于处理 getUserInfo 成功返回的用户信息并打印。
    • 使用 .catch 方法捕获整个过程中可能出现的错误并打印错误信息。

这种方式通过 Promise 的 .then 链式调用,将第二个 Promise 的调用放在第一个 Promise 成功后的回调里,实现了两个异步操作的顺序执行。不过这种方式在处理多个嵌套的 Promise 时,代码会变得难以阅读和维护,也就是所谓的"回调地狱"问题。而使用 async/await 语法可以让代码更加简洁易读。

相关推荐
金銀銅鐵3 小时前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
念何架构之路4 小时前
go-grpc设计思想
开发语言·后端·golang
system_error_x5 小时前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
步行cgn6 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
码事漫谈7 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780518 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123458 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒8 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记8 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk598788 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端