Promise底层实现原理
- 状态机设计与运转
- 状态:Promise有三种状态,分别是
pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。初始状态为pending
。
- 状态转变:
- 当Promise执行成功时,从
pending
转变为fulfilled
,并且会将成功的值传递给后续的then
回调。例如:
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Success value');
}, 1000);
});
- 当Promise执行失败时,从`pending`转变为`rejected`,并将失败原因传递给后续的`catch`回调。例如:
new Promise((resolve, reject) => {
setTimeout(() => {
reject('Error reason');
}, 1000);
});
- 不可逆性:一旦状态从
pending
转变为fulfilled
或rejected
,就不能再改变。
- then方法链式调用实现
then
方法返回一个新的Promise,这是链式调用的基础。例如:
Promise.resolve(1)
.then(value => {
return value + 1;
})
.then(newValue => {
console.log(newValue); // 输出2
});
- 当
then
回调返回一个值时,新的Promise会以这个值被resolve
。如果返回的是一个Promise,新的Promise会“跟随”这个返回的Promise的状态。如果then
回调抛出错误,新的Promise会被rejected
。
高并发网络请求场景下Promise的优化
- Promise本身使用角度
- 批量请求控制:使用
Promise.all
或Promise.race
时,要根据业务场景合理选择。如果需要等待所有请求完成,Promise.all
是合适的;如果只需要第一个完成的请求结果,Promise.race
更优。例如,在批量获取用户数据时:
const userIds = [1, 2, 3];
const userPromises = userIds.map(id => fetch(`/user/${id}`));
Promise.all(userPromises)
.then(responses => {
// 处理所有响应
})
.catch(error => {
// 处理错误
});
- 请求限流:可以通过
async/await
结合setTimeout
来实现简单的请求限流。例如,每秒最多发送3个请求:
async function limitedRequest(urls, limit) {
let index = 0;
const results = [];
while (index < urls.length) {
const batch = urls.slice(index, index + limit);
const batchPromises = batch.map(url => fetch(url));
const batchResults = await Promise.all(batchPromises);
results.push(...batchResults);
index += limit;
if (index < urls.length) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return results;
}
- 底层实现角度
- 优化微任务队列管理:Promise的
then
回调是通过微任务队列执行的。在高并发场景下,可以优化微任务的调度算法,例如采用优先级队列,优先处理重要的Promise回调。
- 减少内存占用:对于已完成的Promise,可以及时释放相关的资源,避免不必要的内存占用。例如,当Promise状态确定后,清理一些中间状态数据。
- 改进事件循环集成:更好地与JavaScript的事件循环机制协同工作,避免在高并发时事件循环过度阻塞,确保其他任务也能得到及时处理。