本文作者:IMWeb chenxd1996 原文出处:IMWeb社区 未经同意,禁止转载
导语:promise相信大家都不陌生,有了promise,配合上async await,再也不用被回调地狱(callback hell) 恶心到。本文我们来简单实现一下Promise。
可以看到promise的规范很详细很明确,只要将规范翻译成代码,就可以实现一个完整的Promise。当然本文只是对Promise的简单实现,一些复杂的情况暂且不考虑。
首先写出Promise的构造函数,Promise使用的是发布与订阅模式,调用promise上的then方法将resolve和reject回调分别加入onFulfilledCallback和onRejectedCallback回调函数集合,
然后调用resolve和reject方法触发回调函数集合中函数的执行。
function Promise(fn) {
var self = this;
self.status = 'pending'; // Promise初始状态为pending
self.data = undefined; // Promise的值
self.onFulfilledCallback = []; // Promise resolve回调函数集合
self.onRejectedCallback = []; // Promise reject回调函数集合
fn(resolve, reject); // 执行传进来的函数,传入resolve, reject参数
}
这里再考虑一下resolve函数和reject函数的实现,在构造函数中定义它们。
function Promise(fn) {
var self = this;
self.status = 'pending'; // Promise初始状态为pending
self.data = undefined; // Promise的值
self.onFulfilledCallback = []; // Promise resolve回调函数集合
self.onRejectedCallback = []; // Promise reject回调函数集合
function resolve(value) {
if (self.status === 'pending') {
self.status = 'resolved';
self.data = value;
for (var i = 0; i < self.onFulfilledCallback.length; i++) {
self.onFulfilledCallback[i](value);
}
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'rejected';
self.data = reason;
for (var i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason);
}
}
}
try {
fn(resolve, reject); // 执行传进来的函数,传入resolve, reject参数
} catch (e) {
reject(e);
}
}
resolve和reject主要做的就是修改promise的状态,然后执行回调函数,逻辑比较简单。
Promise对象有一个then方法,用来注册Promise对象状态确定后的回调。这里需要将then方法定义在Promise的原型上。
Promise.prototype.then = function(onFulfilled, onRejected) {
var self = this;
// 根据标准,如果then的参数不是function,则我们需要忽略它
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(v) { return v};
onRejected = typeof onRejected === 'function' ? onRejected : function(r) { return r };
// Promise对象存在以下三种状态,对三种状态采用不同处理
if (self.status === 'resolved') {
return new Promise(function(resolve, reject) {
// todo
});
}
if (self.status === 'rejected') {
return new Promise(function(resolve, reject) {
// todo
});
}
if (self.status === 'pending') {
return new Promise(function(resolve, reject) {
// todo
});
}
}
接下来,实现对三种情况的处理
Promise.prototype.then = function(onFulfilled, onRejected) {
var self = this;
// 根据标准,如果then的参数不是function,则我们需要忽略它
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(v) { return v};
onRejected = typeof onRejected === 'function' ? onRejected : function(r) { return r };
if (self.status === 'resolved') {
// 这里promise的状态已经确定是resolved,所以调用onResolved
return new Promise(function(resolve, reject) {
try {
// ret是onFulfilled的返回值
var ret = onFulfilled(self.data);
if (ret instanceof Promise) {
// 如果ret是一个promise,则取其值作为新的promise的结果
ret.then(resolve, reject);
} else {
// 否则,以它的返回值作为新的promise的结果
resolve(ret);
}
} catch (e) {
// 如果出错,以捕获到的错误作为promise2的结果
reject(e);
}
});
}
// 这里的逻辑跟前面一样,不再赘述
if (self.status === 'rejected') {
return new Promise(function(resolve, reject) {
try {
var ret = onRejected(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
reject(ret);
}
} catch (e) {
reject(e);
}
});
}
if (self.status === 'pending') {
// 如果当前的Promise还处于pending状态,则不能确定调用
// onResolved还是onRejecte,只能等到Promise状态确定后,
// 才能确定如何处理
return new Promise(function(resolve, reject) {
self.onFulfilledCallback.push(function(value) {
try {
var ret = onFulfilled(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
resolve(ret);
}
} catch (e) {
reject(e);
}
});
self.onRejectedCallback.push(function(value) {
try {
var ret = onRejected(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
reject(ret);
}
} catch (e) {
reject(e);
}
});
});
}
}
// 顺便实现一下catch方法
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
}
根据标准,onFulfilled和onRejected函数需要异步执行,所以我们需要稍微再修改一下代码。
function Promise(fn) {
var self = this;
self.status = 'pending'; // Promise初始状态为pending
self.data = undefined; // Promise的值
self.onFulfilledCallback = []; // Promise resolve回调函数集合
self.onRejectedCallback = []; // Promise reject回调函数集合
function resolve(value) {
if (self.status === 'pending') {
self.status = 'resolved';
self.data = value;
setTimeout(function() {
for (var i = 0; i < self.onFulfilledCallback.length; i++) {
self.onFulfilledCallback[i](value);
}
});
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'rejected';
self.data = reason;
setTimeout(function() {
for (var i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason);
}
});
}
}
try {
fn(resolve, reject); // 执行传进来的函数,传入resolve, reject参数
} catch (e) {
reject(e);
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
var self = this;
// 根据标准,如果then的参数不是function,则我们需要忽略它
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(v) { return v};
onRejected = typeof onRejected === 'function' ? onRejected : function(r) { return r };
if (self.status === 'resolved') {
// 这里promise的状态已经确定是resolved,所以调用onResolved
return new Promise(function(resolve, reject) {
setTimeout(function() {
try {
// ret是onFulfilled的返回值
var ret = onFulfilled(self.data);
if (ret instanceof Promise) {
// 如果ret是一个promise,则取其值作为新的promise的结果
ret.then(resolve, reject);
} else {
// 否则,以它的返回值作为新的promise的结果
resolve(ret);
}
} catch (e) {
// 如果出错,以捕获到的错误作为promise2的结果
reject(e);
}
});
});
}
// 这里的逻辑跟前面一样,不再赘述
if (self.status === 'rejected') {
return new Promise(function(resolve, reject) {
setTimeout(function() {
try {
var ret = onRejected(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
reject(ret);
}
} catch (e) {
reject(e);
}
});
});
}
if (self.status === 'pending') {
// 如果当前的Promise还处于pending状态,则不能确定调用
// onResolved还是onRejecte,只能等到Promise状态确定后,
// 才能确定如何处理
return new Promise(function(resolve, reject) {
self.onFulfilledCallback.push(function(value) {
setTimeout(function() {
try {
var ret = onFulfilled(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
resolve(ret);
}
} catch (e) {
reject(e);
}
});
});
self.onRejectedCallback.push(function(reason) {
setTimeout(function() {
try {
var ret = onRejected(self.data);
if (ret instanceof Promise) {
ret.then(resolve, reject);
} else {
reject(ret);
}
} catch (e) {
reject(e);
}
});
});
});
}
}
// 顺便实现一下catch方法
Promise.prototype.catch = function(onRejected) {
return this.then(null, onRejected);
}
至此,我们已经实现了Promise的基本功能了,让我们来测试一下吧!
const p = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(1);
}, 2000);
});
p.then(function(v) {
console.log(v);
return 2;
}).then(function(v) {
console.log(v);
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(3);
}, 3000);
});
}).then(function(v) {
console.log(v);
});
输出:
1
2
3