掌握Promise本质原理,携手共创全功能实现
2024-01-29 03:39:15
Promise,作为现代前端开发中不可或缺的异步解决方案,凭借其简洁的语法和强大的功能,受到了广泛的应用。在本文中,我们将深入浅出地剖析Promise的原理,并携手构建一个符合Promise A+规范的全功能实现。
Promise的本质与生命周期
Promise,即“承诺”,顾名思义,是一种代表异步操作最终完成或失败的容器。在JavaScript中,Promise对象具有三个状态:
- Pending(等待): Promise初始状态,表示异步操作尚未完成。
- Fulfilled(已完成): 异步操作成功完成,Promise的值已知。
- Rejected(已拒绝): 异步操作失败,Promise的值未知。
Promise的生命周期如下图所示:
[图片]
Promise一旦被创建,便进入Pending状态。当异步操作完成时,Promise的状态会变更为Fulfilled或Rejected,并通过resolve()或reject()方法传递相应的值。状态一旦改变,便不可逆转。
核心方法与实际应用
Promise对象提供了三个核心方法:
- resolve(): 将Promise的状态变更为Fulfilled,并传递一个值作为结果。
- reject(): 将Promise的状态变更为Rejected,并传递一个值作为错误原因。
- then(): 为Promise添加回调函数,当Promise状态改变时,回调函数会被自动调用。
then()方法的语法如下:
then(onFulfilled, onRejected)
其中,onFulfilled和onRejected是可选参数,分别为Promise状态变更为Fulfilled和Rejected时要执行的回调函数。
举个例子,我们有一个获取用户信息的异步函数getUser(),它会返回一个Promise对象。我们希望在用户数据获取成功时,显示用户信息,失败时,显示错误信息。我们可以使用then()方法如下实现:
getUser()
.then(function(user) {
// 用户数据获取成功,显示用户信息
console.log('User:', user);
})
.catch(function(error) {
// 用户数据获取失败,显示错误信息
console.error('Error:', error);
});
全功能实现
现在,让我们携手构建一个全功能的Promise实现。为了符合Promise A+规范,我们需要实现以下几个关键步骤:
- 初始化Promise对象: 构造函数接受一个执行器函数作为参数,执行器函数有两个参数,分别是resolve和reject,用于改变Promise的状态。
- 添加then()方法: then()方法接受两个回调函数作为参数,分别为Promise状态变更为Fulfilled和Rejected时要执行的回调函数。
- 处理then()方法的链式调用: Promise.prototype.then()方法可以被链式调用,即then()方法的返回值仍然是一个Promise对象。
- 处理异常情况: 如果resolve()或reject()方法的参数不是函数,则Promise的状态应该变更为Fulfilled或Rejected,并传递该参数作为结果。
完整的实现代码如下:
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.state !== 'pending') return;
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => callback(value));
};
const reject = (reason) => {
if (this.state !== 'pending') return;
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => callback(reason));
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (error) => { throw error; };
const promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
catch(onRejected) {
return this.then(null, onRejected);
}
finally(onFinally) {
return this.then(
(value) => {
onFinally();
return value;
},
(reason) => {
onFinally();
throw reason;
}
);
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Chaining cycle detected for promise'));
} else if (x instanceof Promise) {
x.then((value) => {
resolvePromise(promise2, value, resolve, reject);
}, reject);
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}
结语
至此,我们已经携手完成了Promise全功能的实现。通过这篇教程,我们不仅深入理解了Promise的原理和生命周期,还掌握了核心方法的使用和全功能实现的细节。这些知识将助你在实际开发中游刃有余地使用Promise,提升异步编程的水平。
实践是检验真理的唯一标准。不妨将本文作为起点,在实际项目中不断探索和实践,相信你会对Promise有更加深入的理解。