Promise 原理与用法
Promise 的状态机制、链式调用与异常处理
问题
解释 Promise 的原理、状态、链式调用与异常处理。
解答
Promise 状态
Promise 有三种状态:
- pending:初始状态,等待中
- fulfilled:操作成功完成
- rejected:操作失败
状态一旦改变就不可逆,只能从 pending 变为 fulfilled 或 rejected。
const promise = new Promise((resolve, reject) => {
// pending 状态
setTimeout(() => {
resolve('成功'); // 变为 fulfilled
// reject('失败'); // 或变为 rejected
}, 1000);
});
基本用法
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve({ id: 1, name: 'Tom' });
} else {
reject(new Error('请求失败'));
}
}, 1000);
});
};
fetchData()
.then(data => console.log(data))
.catch(err => console.error(err));
链式调用
then 返回新的 Promise,支持链式调用:
Promise.resolve(1)
.then(value => {
console.log(value); // 1
return value + 1; // 返回值会被包装成 Promise
})
.then(value => {
console.log(value); // 2
return Promise.resolve(value + 1); // 也可以返回 Promise
})
.then(value => {
console.log(value); // 3
});
异常处理
// 方式一:catch 捕获链上所有错误
Promise.resolve()
.then(() => {
throw new Error('then 中的错误');
})
.then(() => {
console.log('不会执行');
})
.catch(err => {
console.error(err.message); // "then 中的错误"
});
// 方式二:then 的第二个参数(只捕获上一个 then 的错误)
Promise.reject('错误')
.then(
value => console.log(value),
err => console.error(err) // "错误"
);
手写简易 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(fn => fn());
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
// 参数默认值,实现值穿透
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e };
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (err) {
reject(err);
}
});
}
if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (err) {
reject(err);
}
});
}
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolve(x);
} catch (err) {
reject(err);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolve(x);
} catch (err) {
reject(err);
}
});
});
}
});
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
// 测试
new MyPromise((resolve) => {
setTimeout(() => resolve('hello'), 100);
})
.then(val => val + ' world')
.then(val => console.log(val)); // "hello world"
常用静态方法
// Promise.all - 全部成功才成功
Promise.all([
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
]).then(results => console.log(results)); // [1, 2, 3]
// Promise.race - 取最快的结果
Promise.race([
new Promise(r => setTimeout(() => r('慢'), 200)),
new Promise(r => setTimeout(() => r('快'), 100))
]).then(result => console.log(result)); // "快"
// Promise.allSettled - 等待全部完成,不管成功失败
Promise.allSettled([
Promise.resolve(1),
Promise.reject('err')
]).then(results => console.log(results));
// [{status: 'fulfilled', value: 1}, {status: 'rejected', reason: 'err'}]
关键点
- Promise 有三种状态:pending、fulfilled、rejected,状态不可逆
then返回新 Promise,支持链式调用catch能捕获链上所有错误,then第二个参数只捕获上一步错误- 回调通过 setTimeout 实现异步执行(微任务用 queueMicrotask)
Promise.all全部成功才成功,Promise.race取最快结果
目录