Skip to content

关于 Promise 的结果处理

约 636 字大约 2 分钟

JavaScript

2024-05-8

在使用 Promise 的时候,遇到一些误区,同时总结处理 Promise 结果的方法。
对与Promise 的结果处理,需要从 JavaScript 的事件循环和 Promise 状态机角度来理解。

1. const p1 = new Promise(...)

正确用法:

const p1 = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => resolve("成功结果"), 1000);
});

// 通过 .then 获取结果
p1.then(result => {
  console.log("通过 .then 获取到结果:", result); // 输出:"成功结果"
});

resolve 错误用法

const p1 = new Promise((resolve) => {
  resolve(p1); // ❌ 错误!不能将自身作为 resolve 的值
});

// 会导致循环引用,抛出 TypeError: Chaining cycle detected for promise

原因
Promise 的 resolve 参数必须是普通值另一个 Promise。如果传入自身,会导致无限递归(类似 const a = { self: a }),JavaScript 会直接抛出错误。


2. const p1 = await Promise

正确场景:

async function demo() {
  // 假设有一个已解决的 Promise
  const promise = Promise.resolve("结果值");
  
  // 使用 await 提取结果
  const p1 = await promise; // ✅ p1 直接是 "结果值"
  console.log(p1); // 输出:"结果值"
}

demo();

关键点:

  • await自动提取 Promise 的结果值,无需手动调用 .then
  • 如果 Promise 被拒绝(rejected),await 会抛出异常,需要用 try/catch 捕获。

3. 核心区别

场景new Promise + .thenawait 获取结果
类型p1 是 Promise 对象p1 是 Promise 的结果值(非 Promise)
获取结果方式必须通过 .then.catch 处理直接赋值即可
错误处理链式调用 .catchtry/catch 包裹
适用环境所有 JavaScript 环境必须在 async 函数中使用

4. 常见误区

误区 1:混淆 resolve 的参数

// 错误:试图 resolve 自身
new Promise(resolve => resolve(p1)); // ❌ 循环引用

// 正确:resolve 一个值或另一个 Promise
new Promise(resolve => resolve(42)); // ✅ 正确

误区 2:误以为 await 返回 Promise

async function test() {
  const p = await Promise.resolve("value");
  console.log(p); // 输出 "value",而不是 Promise 对象
}

5. 实际应用示例

场景 1:用 .then 处理结果

function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => resolve("数据"), 1000);
  });
}

// 通过 .then 处理
const p1 = fetchData();
p1.then(data => console.log("数据:", data));

场景 2:用 await 直接获取结果

async function handleData() {
  const data = await fetchData(); // 直接得到 "数据"
  console.log("数据:", data);
}

handleData();

6. 总结

  • new Promise:创建一个异步任务,通过 .then/.catch 处理结果。
  • await:在 async 函数中直接提取 Promise 的结果值,代码更简洁。
  • 关键规则
    • resolve 必须传递普通值或另一个 Promise,不能引用自身。
    • await 只能在 async 函数中使用,否则会语法错误。