TypeScript 中,Promise

在 TypeScript 中,Promise 是处理异步操作的核心机制。相比于 JavaScript,TypeScript 中的 Promise 最大的优势在于类型安全(Type Safety),它能让你明确知道异步操作返回的数据类型。

以下是关于 TypeScript 中 Promise 的详细介绍,从基础定义到高级用法。


1. 核心概念与泛型 (Promise<T>)

在 TypeScript 中,Promise 是一个泛型接口,定义为 Promise<T>

  • T : 代表 Promise 成功(Resolved) 时返回的数据类型。
  • 如果 Promise 不返回任何值(只处理过程),通常使用 Promise<void>

基本语法示例

typescript 复制代码
// 显式声明返回类型为 string
const myPromise: Promise<string> = new Promise((resolve, reject) => {
  console.log("异步执行")
  const success = true;  //--------->New的时候 这块代码就被执行
  if (success) {
    resolve("操作成功!"); // 这里的参数必须是 string
  } else {
    reject(new Error("操作失败"));
  }
});
console.log("主程序执行1")
myPromise.then((data) => {   //--------->拿到执行结果
  console.log(data.length); // TS 知道 data 是 string,所以允许访问 .length
});
console.log("主程序执行2")

运行输出结果

typescript 复制代码
[LOG]: "异步执行"  
[LOG]: "主程序执行1"  
[LOG]: "主程序执行2"  
[LOG]: 5

2. 创建 Promise 的方式

2.1 使用构造函数 (new Promise)

这是最基础的写法,构造函数接受一个执行器函数 (resolve, reject) => void

typescript 复制代码
function fetchUser(id: number): Promise<{ id: number; name: string }> {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        // resolve 的参数必须符合 Promise<{...}> 中定义的结构
        resolve({ id, name: "Alice" });
      } else {
        reject("ID 无效");
      }
    }, 1000);
  });
}

2.2 使用 asyncawait (推荐)

这是现代开发的标准写法。async 函数的返回值永远是一个 Promise 。TS 会根据 return 的值自动推断 Promise 的泛型类型。

typescript 复制代码
// 写法 1: 自动推断
async function getUser() {
  return "Alice"; // TS 推断返回类型为 Promise<string>
}

// 写法 2: 显式注解 (推荐,更规范)
async function getScore(): Promise<number> {
  return 100;
}

// 使用 await
async function main() {
  const score = await getScore(); // score 被推断为 number 类型
  console.log(score);
}

3. Promise 的状态与回调

Promise 有三种状态:pending (进行中), fulfilled (已成功), rejected (已失败)。

在 TS 中,.then() 链式调用时,类型会自动流转。

typescript 复制代码
const p = Promise.resolve(10); // 类型: Promise<number>

p.then((num) => {
  // num 是 number
  return num.toString(); // 返回 string
})
.then((str) => {
  // str 是 string (TS 自动推断)
  console.log(str);
  return true; // 返回 boolean
})
.then((bool) => {
  // bool 是 boolean
});

4. 静态方法 (Static Methods)

TypeScript 对 Promise 的静态方法也有很好的类型支持。

4.1 Promise.resolve<T>(value: T)

创建一个立即成功的 Promise。

typescript 复制代码
const p1 = Promise.resolve(42); // Promise<number>
const p2 = Promise.resolve({ name: "Bob" }); // Promise<{ name: string }>

4.2 Promise.reject(reason: any)

创建一个立即失败的 Promise。

typescript 复制代码
const pFail = Promise.reject("Error occurred"); // Promise<never>

4.3 Promise.all<T[]>(values: [])

等待所有 Promise 完成。返回值的类型是一个元组(Tuple)或数组。

typescript 复制代码
const pString = Promise.resolve("Hello");
const pNumber = Promise.resolve(123);

// TS 能够推断出 results 的类型是 [string, number]
Promise.all([pString, pNumber]).then(([str, num]) => {
  console.log(str.toUpperCase()); // 正常
  console.log(num.toFixed(2));    // 正常
});

4.4 Promise.allSettled<T>(...)

等待所有 Promise 完成(无论成功或失败)。

typescript 复制代码
const p1 = Promise.resolve(10);
const p2 = Promise.reject("error");

Promise.allSettled([p1, p2]).then((results) => {
  results.forEach((result) => {
    if (result.status === 'fulfilled') {
      console.log(result.value); // TS 知道这里有 value
    } else {
      console.log(result.reason); // TS 知道这里有 reason
    }
  });
});

4.5 Promise.race<T>(...)

返回第一个改变状态(成功或失败)的 Promise 的结果。


5. 常见实战场景

5.1 定义 API 响应接口

这是前端开发中最常用的模式。

typescript 复制代码
// 1. 定义数据接口
interface User {
  id: number;
  name: string;
  email: string;
}

interface ApiResponse<T> {
  code: number;
  data: T;
  message: string;
}

// 2. 模拟请求函数
function request<T>(url: string): Promise<ApiResponse<T>> {
  return new Promise((resolve) => {
    // 模拟网络请求
    setTimeout(() => {
      resolve({
        code: 200,
        data: {} as T, // 这里只是为了演示,实际会有真实数据
        message: "success"
      });
    }, 500);
  });
}

// 3. 使用
async function fetchUserProfile() {
  // 明确告诉 request 返回的数据结构是 User
  const response = await request<User>('/api/user/1');
  
  if (response.code === 200) {
    // TS 这里会有自动提示:response.data.email
    console.log(response.data.email); 
  }
}

5.2 Promise<void> 用于不返回值的异步操作

例如:初始化数据库、发送日志、等待几秒钟。

typescript 复制代码
function delay(ms: number): Promise<void> {
  return new Promise((resolve) => {
    setTimeout(resolve, ms); // 不需要传递参数给 resolve
  });
}

async function run() {
  console.log("Start");
  await delay(1000);
  console.log("End after 1s");
}

6. 错误处理 (Error Handling)

在 TypeScript 中处理 Promise 错误时,有一个常见的痛点:catch 中的 error 类型通常是 anyunknown

typescript 复制代码
async function task() {
  try {
    await someAsyncOperation();
  } catch (error) {
    // 默认情况下,error 是 unknown 类型 (TS 4.0+) 或 any
    // 你不能直接调用 error.message,除非你进行断言或类型收窄
    
    if (error instanceof Error) {
      console.error(error.message);
    } else {
      console.error("Unknown error:", error);
    }
  }
}

总结

  1. 类型注解 :始终使用 Promise<Type> 来明确异步操作返回的数据结构。
  2. Async/Await :优先使用 async 函数,它让代码看起来像同步代码,且 TS 能自动推断返回类型。
  3. 泛型工具 :利用 Promise.all 等组合工具时,TS 能够很好地处理元组类型推断。
  4. 错误处理 :注意 catch 块中的类型检查,使用 instanceof Error 是个好习惯。

如果你有具体的代码场景需要分析,可以发给我,我帮你进一步讲解!

相关推荐
仅此,4 分钟前
前端接收了id字段,发送给后端就变了
java·前端·javascript·spring·typescript
Lovely Ruby6 分钟前
[前端] 封装一下 echart 6,发布到 npm
前端·npm·node.js
BD_Marathon7 分钟前
NPM_常见命令
前端·npm·node.js
绿鸳11 分钟前
12.17面试题
前端
Huanzhi_Lin24 分钟前
禁用谷歌/google/chrome浏览器更新
前端·chrome
咸鱼加辣28 分钟前
【前端的crud】DOM 就是前端里的“数据库”
前端·数据库
kong790692831 分钟前
环境搭建-运行前端工程(Nginx)
前端·nginx·前端工程
成都证图科技有限公司39 分钟前
Bus Hound概述
前端
PythonFun1 小时前
WPS中表格行高无法手动调整怎么办?
前端·html·wps
IT_陈寒1 小时前
JavaScript性能优化:7个V8引擎内部原理帮你减少90%内存泄漏的实战技巧
前端·人工智能·后端