跳到主要内容

Promise 深入解析与手写实现

1. Promise.all 详细用法​

Promise.all 方法用于将多个 Promise 实例包装成一个新的 Promise。当所有输入的 Promise 都成功时,新的 Promise 才会成功,并返回一个包含所有结果的数组。如果任意一个输入的 Promise 失败,新的 Promise 会立即失败,并返回第一个失败的原因。

使用示例​

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve) => {
setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); // 输出: [3, 42, "foo"]
});

在上述示例中,Promise.all 接收一个包含多个 Promise 的数组。当所有 Promise 都成功时,then 回调会被触发,输出结果数组。

错误处理​

如果任意一个 Promise 被拒绝,Promise.all 会立即返回被拒绝的 Promise。

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => {
setTimeout(reject, 100, 'error');
});
const promise3 = new Promise((resolve) => {
setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values);
})
.catch((error) => {
console.error(error); // 输出: "error"
});

在这个例子中,promise2 被拒绝,导致 Promise.all 立即失败,并返回错误信息。

2. Promise.allSettled 详细用法​

Promise.allSettled 方法接收一组 Promise,返回一个新的 Promise,该 Promise 在所有输入的 Promise 都已完成(无论是成功还是失败)后完成,并返回每个 Promise 的结果状态。

使用示例​

const promise1 = Promise.resolve(42);
const promise2 = Promise.reject('错误发生');
const promise3 = new Promise((resolve) => setTimeout(resolve, 100, 'foo'));

Promise.allSettled([promise1, promise2, promise3]).then((results) => {
console.log(results);
/*
输出:
[
{ status: 'fulfilled', value: 42 },
{ status: 'rejected', reason: '错误发生' },
{ status: 'fulfilled', value: 'foo' }
]
*/
});

Promise.allSettled 不会因为某个 Promise 被拒绝而立即失败,而是会等待所有 Promise 完成,并返回每个 Promise 的状态和结果。

3. Promise.race 详细用法​

Promise.race 方法接收一组 Promise,并返回一个新的 Promise,该 Promise 会在第一个输入的 Promise 完成(无论是成功还是失败)时完成,并返回该 Promise 的结果或错误。

使用示例​

const promise1 = new Promise((resolve) => setTimeout(resolve, 500, 'one'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'two'));

Promise.race([promise1, promise2]).then((value) => {
console.log(value); // 输出: "two"
});

在这个例子中,promise2 比 promise1 先完成,因此 Promise.race 返回 promise2 的结果。

处理拒绝情况​

const promise1 = new Promise((resolve, reject) => setTimeout(reject, 200, 'error'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'success'));

Promise.race([promise1, promise2])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // 输出: "error"
});

如果第一个完成的 Promise 是被拒绝的,Promise.race 会返回该错误。

4. Promise.any 详细用法​

Promise.any 方法接收一组 Promise,并返回一个新的 Promise,该 Promise 在第一个成功的输入 Promise 完成时成功,并返回该 Promise 的结果。如果所有输入的 Promise 都被拒绝,则返回一个 AggregateError 错误。

使用示例​

const promise1 = Promise.reject('失败');
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, '成功'));

Promise.any([promise1, promise2]).then((value) => {
console.log(value); // 输出: "成功"
});

在此示例中,虽然 promise1 被拒绝,但 promise2 成功完成,因此 Promise.any 返回 promise2 的结果。

所有 Promise 被拒绝​

const promise1 = Promise.reject('失败1');
const promise2 = Promise.reject('失败2');

Promise.any([promise1, promise2])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // 输出: AggregateError: All promises were rejected
});

当所有输入的 Promise 都被拒绝时,Promise.any 返回一个包含所有错误的 AggregateError。

5. Promise.reject 和 Promise.resolve​

Promise.resolve 和 Promise.reject 是用于创建已解决或已拒绝状态的 Promise 的快捷方法。

Promise.resolve​

Promise.resolve 用于创建一个立即解决的 Promise。

const resolvedPromise = Promise.resolve('成功');
resolvedPromise.then((value) => {
console.log(value); // 输出: "成功"
});

如果传入一个 Promise 对象,Promise.resolve 会返回该 Promise 对象。

const existingPromise = new Promise((resolve) => resolve('已有的 Promise'));
const resolvedPromise = Promise.resolve(existingPromise);
console.log(existingPromise === resolvedPromise); // 输出: true

Promise.reject​

Promise.reject 用于创建一个立即拒绝的 Promise。

const rejectedPromise = Promise.reject('失败原因');
rejectedPromise.catch((reason) => {
console.error(reason); // 输出: "失败原因"
});

这两个方法常用于在异步函数中快速返回已解决或已拒绝的 Promise。

6. 手写 Promise.all 原理​

实现 Promise.all 的核心在于同时执行多个 Promise,并在所有 Promise 都成功时返回它们的结果。如果任何一个 Promise 被拒绝,则立即返回该错误。

实现思路​

  1. 接收一个包含多个 Promise 的可迭代对象。
  2. 返回一个新的 Promise。
  3. 遍历输入的 Promise,逐一执行并收集结果。
  4. 使用计数器跟踪已完成的 Promise 数量。
  5. 如果任意一个 Promise 被拒绝,立即拒绝新的 Promise。
  6. 当所有 Promise 都成功时,解决新的 Promise,并返回结果数组。

7. 手写 Promise.all 代码​

function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数必须是一个数组'));
}

const results = [];
let completed = 0;

if (promises.length === 0) {
return resolve([]);
}

promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((value) => {
results[index] = value;
completed += 1;
if (completed === promises.length) {
resolve(results);
}
})
.catch((error) => {
reject(error);
});
});
});
}

代码解析​

  • 输入验证: 首先检查输入是否为数组,如果不是,则返回一个 TypeError。
  • 结果收集: 使用 results 数组按照输入顺序存储每个 Promise 的结果。
  • 计数器: 使用 completed 变量跟踪已完成的 Promise 数量。
  • 异步处理: 使用 Promise.resolve 确保每个输入项都是一个 Promise。
  • 错误处理: 如果任何一个 Promise 被拒绝,立即拒绝整个 myPromiseAll。

8. 手写 Promise.all 测试​

// 测试用例
const promise1 = Promise.resolve(1);
const promise2 = 2;
const promise3 = new Promise((resolve) => setTimeout(resolve, 100, 3));

myPromiseAll([promise1, promise2, promise3])
.then((values) => {
console.log(values); // 输出: [1, 2, 3]
})
.catch((error) => {
console.error(error);
});

// 测试拒绝情况
const promise4 = Promise.reject('失败');

myPromiseAll([promise1, promise4, promise3])
.then((values) => {
console.log(values);
})
.catch((error) => {
console.error(error); // 输出: "失败"
});

测试说明​

  • 成功场景: 所有 Promise 都成功,myPromiseAll 返回结果数组。
  • 失败场景: 存在一个被拒绝的 Promise,myPromiseAll 立即被拒绝,并返回错误信息。

9. 手写 Promise.race​

Promise.race 方法接收一组 Promise,并返回一个新的 Promise,该 Promise 会在第一个输入的 Promise 完成(无论是成功还是失败)时完成,并返回该 Promise 的结果或错误。

实现思路​

  1. 接收一个包含多个 Promise 的可迭代对象。
  2. 返回一个新的 Promise。
  3. 遍历输入的 Promise,逐一执行。
  4. 一旦有一个 Promise 完成(无论成功或失败),立即解决或拒绝新的 Promise。

10. 手写 Promise.race 代码测试​

function myPromiseRace(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数必须是一个数组'));
}

for (let promise of promises) {
Promise.resolve(promise)
.then((value) => {
resolve(value);
})
.catch((error) => {
reject(error);
});
}
});
}

// 测试用例
const racePromise1 = new Promise((resolve) => setTimeout(resolve, 500, 'one'));
const racePromise2 = new Promise((resolve) => setTimeout(resolve, 100, 'two'));

myPromiseRace([racePromise1, racePromise2])
.then((value) => {
console.log(value); // 输出: "two"
})
.catch((error) => {
console.error(error);
});

// 测试拒绝情况
const racePromise3 = new Promise((resolve, reject) => setTimeout(reject, 50, 'error'));
const racePromise4 = new Promise((resolve) => setTimeout(resolve, 100, 'success'));

myPromiseRace([racePromise3, racePromise4])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // 输出: "error"
});

测试说明​

  • 第一个完成的 Promise: 无论是成功还是失败,myPromiseRace 都会返回第一个完成的 Promise 的结果或错误。
  • 拒绝优先: 如果第一个完成的是被拒绝的 Promise,myPromiseRace 会返回该错误。

11. 手写 Promise.allSettled​

Promise.allSettled 方法接收一组 Promise,返回一个新的 Promise,该 Promise 在所有输入的 Promise 都已完成(无论是成功还是失败)后完成,并返回每个 Promise 的结果状态。

实现思路​

  1. 接收一个包含多个 Promise 的可迭代对象。
  2. 返回一个新的 Promise。
  3. 遍历输入的 Promise,逐一执行并收集结果。
  4. 使用计数器跟踪已完成的 Promise 数量。
  5. 无论每个 Promise 是成功还是失败,都记录其状态和结果。
  6. 当所有 Promise 完成后,解决新的 Promise,并返回结果数组。

12. Promise.allSettled 代码测试​

function myPromiseAllSettled(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数必须是一个数组'));
}

const results = [];
let completed = 0;

if (promises.length === 0) {
return resolve([]);
}

promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((value) => {
results[index] = { status: 'fulfilled', value };
})
.catch((reason) => {
results[index] = { status: 'rejected', reason };
})
.finally(() => {
completed += 1;
if (completed === promises.length) {
resolve(results);
}
});
});
});
}

// 测试用例
const settledPromise1 = Promise.resolve(1);
const settledPromise2 = Promise.reject('失败');
const settledPromise3 = new Promise((resolve) => setTimeout(resolve, 100, 3));

myPromiseAllSettled([settledPromise1, settledPromise2, settledPromise3])
.then((results) => {
console.log(results);
/*
输出:
[
{ status: 'fulfilled', value: 1 },
{ status: 'rejected', reason: '失败' },
{ status: 'fulfilled', value: 3 }
]
*/
})
.catch((error) => {
console.error(error);
});

测试说明​

  • 混合结果: myPromiseAllSettled 会返回每个 Promise 的状态和结果,无论是成功还是失败。
  • 全部完成: 只有当所有 Promise 都完成后,myPromiseAllSettled 才会解决新的 Promise。

13. 手写 Promise.any​

Promise.any 方法接收一组 Promise,并返回一个新的 Promise,该 Promise 在第一个成功的输入 Promise 完成时成功,并返回该 Promise 的结果。如果所有输入的 Promise 都被拒绝,则返回一个 AggregateError 错误。

实现思路​

  1. 接收一个包含多个 Promise 的可迭代对象。
  2. 返回一个新的 Promise。
  3. 遍历输入的 Promise,逐一执行。
  4. 记录所有拒绝的原因。
  5. 一旦有一个 Promise 成功,立即解决新的 Promise 并返回结果。
  6. 如果所有 Promise 都被拒绝,拒绝新的 Promise 并返回 AggregateError。

14. 手写 Promise.any 代码测试​

function myPromiseAny(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数必须是一个数组'));
}

const errors = [];
let rejectedCount = 0;

if (promises.length === 0) {
return reject(new AggregateError([], 'All promises were rejected'));
}

promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((value) => {
resolve(value);
})
.catch((error) => {
errors[index] = error;
rejectedCount += 1;
if (rejectedCount === promises.length) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
});
});
});
}

// 测试用例
const anyPromise1 = Promise.reject('失败1');
const anyPromise2 = new Promise((resolve) => setTimeout(resolve, 100, '成功'));

myPromiseAny([anyPromise1, anyPromise2])
.then((value) => {
console.log(value); // 输出: "成功"
})
.catch((error) => {
console.error(error);
});

// 测试所有拒绝
const anyPromise3 = Promise.reject('失败2');
const anyPromise4 = Promise.reject('失败3');

myPromiseAny([anyPromise3, anyPromise4])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // 输出: AggregateError: All promises were rejected
});

测试说明​

  • 成功场景: 任意一个 Promise 成功,myPromiseAny 返回该结果。
  • 全部拒绝: 所有 Promise 都被拒绝,myPromiseAny 返回 AggregateError。

15. 手写 Promise.last​

Promise.last 是一个自定义的 Promise 方法,它会等待所有输入的 Promise 完成,并返回最后一个完成的 Promise 的结果。如果最后一个完成的 Promise 被拒绝,则返回该错误。

实现思路​

  1. 接收一个包含多个 Promise 的可迭代对象。
  2. 返回一个新的 Promise。
  3. 遍历输入的 Promise,逐一执行。
  4. 记录每个 Promise 的完成顺序。
  5. 当所有 Promise 完成后,返回最后一个完成的 Promise 的结果或错误。

16. 手写 Promise.last 代码测试​

function myPromiseLast(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('参数必须是一个数组'));
}

if (promises.length === 0) {
return resolve();
}

let lastIndex = -1;
let completed = 0;

promises.forEach((promise, index) => {
Promise.resolve(promise)
.then((value) => {
if (index > lastIndex) {
lastIndex = index;
}
completed += 1;
if (completed === promises.length) {
resolve(promises[lastIndex]);
}
})
.catch((error) => {
if (index > lastIndex) {
lastIndex = index;
}
completed += 1;
if (completed === promises.length) {
reject(error);
}
});
});
});
}

// 测试用例
const lastPromise1 = new Promise((resolve) => setTimeout(resolve, 100, 'first'));
const lastPromise2 = new Promise((resolve) => setTimeout(resolve, 200, 'second'));
const lastPromise3 = new Promise((resolve) => setTimeout(resolve, 300, 'third'));

myPromiseLast([lastPromise1, lastPromise2, lastPromise3])
.then((value) => {
console.log(value); // 输出: "third"
})
.catch((error) => {
console.error(error);
});

// 测试最后一个被拒绝
const lastPromise4 = new Promise((resolve) => setTimeout(resolve, 100, 'first'));
const lastPromise5 = new Promise((resolve, reject) => setTimeout(reject, 200, 'error'));

myPromiseLast([lastPromise4, lastPromise5])
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error(error); // 输出: "error"
});

测试说明​

  • 成功场景: 返回最后一个完成的 Promise 的结果。
  • 拒绝场景: 如果最后一个完成的 Promise 被拒绝,返回该错误。

17. 手写 Promise.queue​

Promise.queue 是一个自定义的 Promise 方法,用于控制一组异步任务的执行顺序,确保任务按照指定的顺序一个接一个地执行。

实现思路​

  1. 接收一个包含异步任务的数组,每个任务返回一个 Promise。
  2. 按照数组顺序执行每个任务。
  3. 等待当前任务完成后再执行下一个任务。
  4. 返回一个包含所有任务结果的数组。

18. 手写并发请求题目​

编写一个函数 fetchUrlsInQueue(urls, limit),该函数接受一个 URL 数组和并发限制数 limit,并按顺序发送 HTTP 请求,最多同时进行 limit 个请求。函数应返回一个包含所有请求结果的数组。

实现思路​

  1. 使用一个队列来管理待执行的请求。
  2. 保持同时进行的请求数量不超过 limit。
  3. 依次执行队列中的请求,并收集结果。
  4. 当所有请求完成后,返回结果数组。

19. 手写并发控制​

function fetchUrlsInQueue(urls, limit) {
return new Promise((resolve, reject) => {
const results = [];
let inFlight = 0;
let currentIndex = 0;

function enqueue() {
if (currentIndex === urls.length && inFlight === 0) {
resolve(results);
return;
}

while (inFlight < limit && currentIndex < urls.length) {
const index = currentIndex;
const url = urls[currentIndex];
currentIndex += 1;
inFlight += 1;

fetch(url)
.then((response) => response.text())
.then((data) => {
results[index] = data;
inFlight -= 1;
enqueue();
})
.catch((error) => {
reject(error);
});
}
}

enqueue();
});
}

// 使用示例
const urls = [
'https://jsonplaceholder.typicode.com/posts/1',
'https://jsonplaceholder.typicode.com/posts/2',
'https://jsonplaceholder.typicode.com/posts/3',
'https://jsonplaceholder.typicode.com/posts/4',
'https://jsonplaceholder.typicode.com/posts/5',
];

fetchUrlsInQueue(urls, 2)
.then((results) => {
console.log(results);
})
.catch((error) => {
console.error(error);
});

测试说明​

  • 并发限制: 同时进行的请求数量不超过 limit。
  • 结果顺序: 结果数组中的数据顺序与输入的 URL 顺序一致。

20. 使用闭包优化并发请求结果顺序​

在并发请求中,由于请求的完成顺序不确定,使用闭包可以确保结果按照请求的顺序存储。

实现思路​

  1. 使用闭包保存每个请求的索引。
  2. 在请求完成时,将结果存储到对应的索引位置。
  3. 确保最终结果数组的顺序与输入顺序一致。

21. 手写 Promisify​

Promisify 是将基于回调的异步函数转换为返回 Promise 的函数的过程。

实现思路​

  1. 接收一个基于回调的函数。
  2. 返回一个新的函数,该函数返回一个 Promise。
  3. 在新的函数中调用原始函数,并在回调中解析或拒绝 Promise。

实现代码​

function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn(...args, (error, result) => {
if (error) {
return reject(error);
}
resolve(result);
});
});
};
}

// 使用示例
const fs = require('fs');

const readFileAsync = promisify(fs.readFile);

readFileAsync('example.txt', 'utf8')
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error(error);
});

测试说明​

  • 成功场景: 回调函数调用 resolve。
  • 拒绝场景: 回调函数调用 reject。

22. async、await 微任务代码输出 1​

async 和 await 是用于简化 Promise 使用的语法糖。它们基于微任务队列,确保异步代码按预期执行。

示例代码​

async function asyncFunction() {
console.log('开始');

const promise = new Promise((resolve) => {
setTimeout(() => {
resolve('完成');
}, 1000);
});

const result = await promise;
console.log(result);
}

asyncFunction();
console.log('同步代码');

输出说明​

执行顺序如下:

  1. 输出: "开始"
  2. 输出: "同步代码"
  3. 等待 1 秒后输出: "完成"

这是因为 await 会等待 Promise 解析,但不会阻塞主线程,后续的同步代码会继续执行。

23. Promise A+ 规范​

Promise A+ 是一个规范,定义了 Promise 的行为和状态转换。它确保了不同实现之间的一致性,使得 Promise 可以互操作。

主要内容​

  • 状态: Promise 有三种状态:待定(pending)、已兑现(fulfilled)、已拒绝(rejected)。
  • then 方法: then 方法用于注册回调,接收两个参数:成功回调和失败回调。
  • 链式调用: then 方法返回一个新的 Promise,支持链式调用。
  • 错误传递: 异常会传递到下一个 catch 回调。
  • 解析过程: 当一个 Promise 被解析为另一个 Promise 时,必须遵循一定的解析规则,确保正确的状态转换。

重要规则​

  1. then 方法必须返回一个新的 Promise。
  2. 如果回调返回一个值,新 Promise 被解决为该值。
  3. 如果回调抛出错误,新 Promise 被拒绝为该错误。
  4. 如果回调返回一个 Promise,新 Promise 的状态取决于该 Promise。

这些规则确保了 Promise 的行为符合预期,并且不同的实现可以互相兼容。

24. 手写 Promise​

手写一个简单的 Promise 实现,遵循基本的 Promise 行为。

实现代码​

class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];

const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(value));
}
};

const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(reason));
}
};

try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}

then(onFulfilled, onRejected) {
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (error) {
reject(error);
}
}

if (this.state === 'rejected') {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (error) {
reject(error);
}
}

if (this.state === 'pending') {
this.onFulfilledCallbacks.push((value) => {
try {
const x = onFulfilled(value);
resolve(x);
} catch (error) {
reject(error);
}
});

this.onRejectedCallbacks.push((reason) => {
try {
const x = onRejected(reason);
resolve(x);
} catch (error) {
reject(error);
}
});
}
});

return promise2;
}

catch(onRejected) {
return this.then(null, onRejected);
}
}

// 使用示例
const myPromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('成功');
}, 1000);
});

myPromise
.then((value) => {
console.log(value); // 输出: "成功"
return '下一步';
})
.then((value) => {
console.log(value); // 输出: "下一步"
})
.catch((error) => {
console.error(error);
});

实现说明​

  • 状态管理: 使用 state 属性跟踪 Promise 的状态。
  • 回调队列: 使用 onFulfilledCallbacks 和 onRejectedCallbacks 数组存储回调函数,确保在异步情况下正确执行。
  • then 方法: 返回一个新的 Promise,实现链式调用。
  • 错误处理: 使用 try-catch 捕获执行过程中的错误,并通过 reject 传递。

25. Promise 链式调用与错误处理​

Promise 的链式调用允许多个异步操作按顺序执行,每个操作的结果可以传递给下一个操作。错误处理则通过 catch 方法捕获链中任意位置的错误。

链式调用示例​

new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1);
}, 1000);
})
.then((value) => {
console.log(value); // 输出: 1
return value + 1;
})
.then((value) => {
console.log(value); // 输出: 2
return new Promise((resolve) => setTimeout(() => resolve(value + 1), 1000));
})
.then((value) => {
console.log(value); // 输出: 3
})
.catch((error) => {
console.error(error);
});

错误处理示例​

new Promise((resolve, reject) => {
setTimeout(() => {
resolve('开始');
}, 500);
})
.then((value) => {
console.log(value); // 输出: "开始"
throw new Error('中间出错');
})
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error('捕获错误:', error.message); // 输出: "捕获错误: 中间出错"
});

多重错误处理​

在链式调用中,错误可以在任意位置被捕获。以下示例展示了多个 catch 的用法。

new Promise((resolve, reject) => {
resolve('任务1');
})
.then((value) => {
console.log(value); // 输出: "任务1"
return '任务2';
})
.then((value) => {
console.log(value); // 输出: "任务2"
throw new Error('任务3 出错');
})
.catch((error) => {
console.error('捕获错误:', error.message); // 输出: "捕获错误: 任务3 出错"
return '错误处理后继续';
})
.then((value) => {
console.log(value); // 输出: "错误处理后继续"
})
.catch((error) => {
console.error(error);
});

在此示例中,第一个 catch 捕获了第三个任务的错误,并通过返回一个值继续了链式调用。第二个 catch 只会捕获后续链中的错误。