返回
重塑可靠承诺:深入探索Promise实现的艺术
前端
2023-09-28 19:08:23
拥抱异步编程新范式:深入浅出解剖Promise
缘起:告别回调地狱
在异步编程的领域,回调函数曾独领风骚。然而,随着异步操作的日益繁复,回调地狱的幽灵也随之而来。嵌套的回调函数层层叠加,代码结构变得难以维护和理解。为了解决这一痛点,Promise应运而生。
Promise的本质:占位符与优雅处理
Promise,意为“承诺”,本质上是一种表示异步操作最终完成或失败的占位符。它提供了一种更优雅的方式来处理异步操作的结果,避免回调地狱的困扰。Promise具有三个状态:等待、已完成和已拒绝。
构建自己的Promise:理解其运作原理
为了更深入理解Promise的运作机制,不妨亲手构建一个基于A+规范的Promise实现。A+规范定义了Promise的标准行为,确保不同实现之间的一致性。代码如下:
// Promise 实现
class Promise {
constructor(executor) {
this.state = 'pending';
this.result = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 立即执行executor,传入resolve和reject函数
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(result) {
// 确保resolve和reject只能调用一次
if (this.state !== 'pending') {
return;
}
this.state = 'fulfilled';
this.result = result;
// 依次调用所有已注册的onFulfilled回调函数
this.onFulfilledCallbacks.forEach(callback => callback(result));
}
reject(error) {
// 确保resolve和reject只能调用一次
if (this.state !== 'pending') {
return;
}
this.state = 'rejected';
this.result = error;
// 依次调用所有已注册的onRejected回调函数
this.onRejectedCallbacks.forEach(callback => callback(error));
}
then(onFulfilled, onRejected) {
// 允许then方法可以不传参数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
// 返回一个新的Promise
return new Promise((resolve, reject) => {
// 根据当前Promise的状态,立即调用相应的回调函数
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this.result);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const error = onRejected(this.result);
resolve(error);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 如果当前Promise仍处于等待状态,将回调函数加入相应的队列
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const result = onFulfilled(this.result);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const error = onRejected(this.result);
resolve(error);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
return this.then(
result => {
onFinally();
return result;
},
error => {
onFinally();
throw error;
}
);
}
}
ES6-Promise:标准化实现
ES6-Promise作为Promise的标准实现,在浏览器和Node.js中都得到了广泛支持。它的实现更为精巧,提供了更丰富的功能。代码如下:
// ES6-Promise 实现
class Promise {
constructor(executor) {
this._state = 'pending';
this._result = undefined;
this._onFulfilledCallbacks = [];
this._onRejectedCallbacks = [];
// 立即执行executor,传入resolve和reject函数
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(result) {
// 确保resolve和reject只能调用一次
if (this._state !== 'pending') {
return;
}
this._state = 'fulfilled';
this._result = result;
// 依次调用所有已注册的onFulfilled回调函数
this._onFulfilledCallbacks.forEach(callback => callback(result));
}
reject(error) {
// 确保resolve和reject只能调用一次
if (this._state !== 'pending') {
return;
}
this._state = 'rejected';
this._result = error;
// 依次调用所有已注册的onRejected回调函数
this._onRejectedCallbacks.forEach(callback => callback(error));
}
then(onFulfilled, onRejected) {
// 允许then方法可以不传参数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error; };
// 返回一个新的Promise
return new Promise((resolve, reject) => {
// 根据当前Promise的状态,立即调用相应的回调函数
if (this._state === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this._result);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this._state === 'rejected') {
setTimeout(() => {
try {
const error = onRejected(this._result);
resolve(error);
} catch (error) {
reject(error);
}
}, 0);
} else {
// 如果当前Promise仍处于等待状态,将回调函数加入相应的队列
this._onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const result = onFulfilled(this._result);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
this._onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const error = onRejected(this._result);
resolve(error);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
return this.then(
result => {
onFinally();
return result;
},
error => {
onFinally();
throw error;
}
);
}
// ES6-Promise新增的静态方法
static resolve(value) {
return new Promise((resolve, reject) => {
resolve(value);
});
}
static reject(error) {
return new Promise((resolve, reject) => {
reject(error);
});
}
static all(promises) {
return new Promise((resolve, reject) => {
const results = [];
let pendingCount = promises.length;
promises.forEach((promise, index) => {
promise
.then(result => {
results[index] = result;
pendingCount--;
if (pendingCount === 0) {
resolve(results);
}
})
.catch(error => {
reject(error);
});
});
});
}
}
常见问题解答
1. Promise与回调函数有什么区别?
Promise提供了一种更优雅的方式来处理异步操作的结果,避免回调地狱的困扰。Promise允许使用链式调用,使代码结构更加清晰易读