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 被拒绝,则立即返回该错误。
实现思路
- 接收一个包含多个 Promise 的可迭代对象。
- 返回一个新的 Promise。
- 遍历输入的 Promise,逐一执行并收集结果。
- 使用计数器跟踪已完成的 Promise 数量。
- 如果任意一个 Promise 被拒绝,立即拒绝新的 Promise。
- 当所有 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 的结果或错误。
实现思路
- 接收一个包含多个 Promise 的可迭代对象。
- 返回一个新的 Promise。
- 遍历输入的 Promise,逐一执行。
- 一旦有一个 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 的结果状态。
实现思路
- 接收一个包含多个 Promise 的可迭代对象。
- 返回一个新的 Promise。
- 遍历输入的 Promise,逐一执行并收集结果。
- 使用计数器跟踪已完成的 Promise 数量。
- 无论每个 Promise 是成功还是失败,都记录其状态和结果。
- 当所有 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 错误。
实现思路
- 接收一个包含多个 Promise 的可迭代对象。
- 返回一个新的 Promise。
- 遍历输入的 Promise,逐一执行。
- 记录所有拒绝的原因。
- 一旦有一个 Promise 成功,立即解决新的 Promise 并返回结果。
- 如果所有 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 被拒绝,则返回该错误。
实现思路
- 接收一个包含多个 Promise 的可迭代对象。
- 返回一个新的 Promise。
- 遍历输入的 Promise,逐一执行。
- 记录每个 Promise 的完成顺序。
- 当所有 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 方法,用于控制一组异步任务的执行顺序,确保任务按照指定的顺序一个接一个地执行。
实现思路
- 接收一个包含异步任务的数组,每个任务返回一个 Promise。
- 按照数组顺序执行每个任务。
- 等待当前任务完成后再执行下一个任务。
- 返回一个包含所有任务结果的数组。
18. 手写并发请求题目
编写一个函数 fetchUrlsInQueue(urls, limit)
,该函数接受一个 URL 数组和并发限制数 limit
,并按顺序发送 HTTP 请求,最多同时进行 limit
个请求。函数应返回一个包含所有请求结果的数组。
实现思路
- 使用一个队列来管理待执行的请求。
- 保持同时进行的请求数量不超过
limit
。 - 依次执行队列中的请求,并收集结果。
- 当所有请求完成后,返回结果数组。
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. 使用闭包优化并发请求结果顺序
在并发请求中,由于请求的完成顺序不确定,使用闭包可以确保结果按照请求的顺序存储。
实现思路
- 使用闭包保存每个请求的索引。
- 在请求完成时,将结果存储到对应的索引位置。
- 确保最终结果数组的顺序与输入顺序一致。
21. 手写 Promisify
Promisify
是将基于回调的异步函数转换为返回 Promise 的函数的过程。
实现思路
- 接收一个基于回调的函数。
- 返回一个新的函数,该函数返回一个 Promise。
- 在新的函数中调用原始函数,并在回调中解析或拒绝 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 秒后输出: "完成"
这是因为 await
会等待 Promise 解析,但不会阻塞主线程,后续的同步代码会继续执行。
23. Promise A+ 规范
Promise A+ 是一个规范,定义了 Promise 的行为和状态转换。它确保了不同实现之间的一致性,使得 Promise 可以互操作。
主要内容
- 状态: Promise 有三种状态:待定(pending)、已兑现(fulfilled)、已拒绝(rejected)。
- then 方法:
then
方法用于注册回调,接收两个参数:成功回调和失败回调。 - 链式调用:
then
方法返回一个新的 Promise,支持链式调用。 - 错误传递: 异常会传递到下一个
catch
回调。 - 解析过程: 当一个 Promise 被解析为另一个 Promise 时,必须遵循一定的解析规则,确保正确的状态转换。
重要规则
- then 方法必须返回一个新的 Promise。
- 如果回调返回一个值,新 Promise 被解决为该值。
- 如果回调抛出错误,新 Promise 被拒绝为该错误。
- 如果回调返回一个 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
只会捕获后续链中的错误。