认识
一、认识
Promise
提供了一种比传统回调或事件机制更直观、更易于维护的异步处理方式,能有效解决 回调地狱 和错误处理分散的问题。Promise
遵循 Promise/A+
规范,确保其行为具有可预测性和一致性。它使得异步操作的链式调用和错误传递变得简单。
Promise
变更状态, Promise
的状态可以通过以下三种方式变更: resolve()
: 将 Promise
的Pending
状态置为Fulfilled
; reject()
: 用于将 Promise
的Pending
状态置为Rejected
; throw()
: 用于将 Promise
的 Pending
状态置为 Rejected
Promise
异常穿透: Promise
内部任何操作出错(无论是在构造函数中,还是 then
回调内抛出异常),都会导致当前 Promise
被拒绝,而这个错误会沿着链 冒泡, 直到遇到下一个 catch
回调。因此, 无论在链的哪个环节出错, 最终都可以在链的末尾统一捕获并处理。但是, 如果在 then
的成功回调中抛出异常, 这个异常不会被同一个 then
的失败回调捕获, 而是传递给后续的 catch
或 then
的失败分支。这使得错误处理更集中, 也要求开发者在链式调用的最后一定要有 catch
, 以防止未处理的异常(某些环境下未处理的 Promise
拒绝可能会导致警告或者程序崩溃)。
Promise
异常捕获: 如果 Promise
被拒绝且没有 catch
捕获, 在 Node.js
和现代浏览器中可能会触发 unhandledRejection
事件。如果 Promise
被拒绝但是被 catch
捕获, 会触发 rejectionHandled
事件。
二、语法
new Promise((resolve,reject)=>{
if(true){
resolve(1);
}else{
reject(2);
}
}).then(res=>{
console.log(res);
}).catch(error=>{
console.log(error)
});
三、特点
3.1 状态
Promise
对象代表一个异步操作,有三种状态:
-
pending
(进行中) -
fulfilled
(已成功) -
rejected
(已失败)
Promise
状态一旦改变, 就不会在变。Promise
的状态改变,只有两种可能: 从 pending
变为 fulfilled
和从 pending
变为 rejected
。只要这两种情况发生, 状态就凝固了,不会再变了。
Promise
改变状态的方式有以下三种:
-
resolve()
: 将Promise的Pending
状态置为Fulfilled
-
reject()
: 用于将Promise的Pending
状态置为Rejected
-
throw()
: 用于将Promise的Pending
状态置为Rejected
3.2 弊端
-
无法取消
Promise
,一旦新建new Promise
就会立即执行,无法中途取消。 -
如果不设置回调函数,
Promise
内部抛出的错误,不会反应到外部。 -
当处于
pending
状态时, 无法得知目前进展到了哪一阶段(刚刚开始还是即将完成)
四、检测
描述 检测环境是否支持 Promise
function isNative(Ctor){
return typeof Ctor === 'function' && /native code/.test(Ctor.toString());
}
function isSupportPromise(){
return typeof Promise !== 'undefined' && isNative(Promise);
}
四、问题
4.1 如何中断 Promise 的执行?
一、使用 AbortController
中断: 首先创建了一个新的 AbortController
实例和对应的 signal
。然后,在 Promise
内部,我们设置了一个计时器来模拟异步操作,并在5秒后解决 Promise
。同时,我们监听 signal
上的 abort
事件,以便在 Promise
被中止时清除计时器并拒绝 Promise
。最后,我们使用 controller.abort()
方法来中止 Promise
。
const controller = new AbortController();
const signal = controller.signal;
const promise = new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
resolve("Promise resolved");
}, 5000);
// 监听 signal 是否被中止
signal.addEventListener("abort", () => {
clearTimeout(timeoutId);
reject(new Error("Promise aborted"));
});
});
// 中止 Promise
controller.abort();
二、使用闭包和标记变量: 我们将 cancel
方法定义为一个变量, 在 Promise
构造函数内部创建, 然后将其赋值给 promise
对象的 cancel
属性。这样就能够成功地调用 myPromise.cancel()
来取消 Promise
function createCancelablePromise() {
let isCanceled = false;
let cancel;
const promise = new Promise((resolve, reject) => {
// 模拟一个异步操作
const timeoutId = setTimeout(() => {
if (!isCanceled) {
resolve("Promise resolved");
}
}, 5000);
// 中断函数
cancel = function() {
isCanceled = true;
clearTimeout(timeoutId);
reject(new Error("Promise canceled"));
};
});
promise.cancel = cancel;
return promise;
}
const myPromise = createCancelablePromise();
// 在某个条件下中断 Promise
myPromise.cancel();
4.2 Promise 的状态为什么一经变更, 无法改变呢?
Promise
的状态可以通过以下三种方式变更: resolve()
: 将 Promise
的Pending
状态置为Fulfilled
; reject()
: 用于将 Promise
的Pending
状态置为Rejected
; throw()
: 用于将 Promise
的 Pending
状态置为 Rejected
。其中:
-
Promise.prototype.resolve
内部首先检测当前Promise
状态是否为Pending
, 只有处于Pending
的状态下, 执行后续resolve
的逻辑。比如改变Promise
状态为Fulfilled
, 遍历存储的成功回调数组, 执行每一个回调。 -
Promise.prototype.reject
同理, 内部首先检测当前Promise
状态是否为Pending
, 只有处于Pending
的状态下, 执行后续reject
的逻辑。比如改变Promise
状态为Rejected
, 遍历存储的失败回调数组, 执行每一个回调。