初始化
我们知道Promise内部有三种状态,因此我们定义status:
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
}
其次,在Promise兑现和拒绝的时候,需要有变量来存储值,也就是then()中回调可以接收的值。then((res)=>{})的这个res
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
value = undefined
reason = undefined
}
接下来我们思考构造函数,我们考虑new Promise(executor), 这里会接收executor,excutor是什么形式呢?(resolve,reject)=> {}, 其中resolve和reject是可以改变Promise状态的函数,可以给Promise调用。因此我们考虑写出以下代码:
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
value = undefined
reason = undefined
construct(executor){
const reject = (val) => {
this.status = REJECTED
this.value = val
}
const resolve = (reason) => {
this.status = FULFILLED
this.reason = reason
}
try{
// 从这里我们可以知道new Promise(executor)中的executor是同步代码,会执行一次
executor(resolve, reject)
}catch(e){
reject(e)
}
}
}
然后我们考虑实现then方法,then(onFulfilled, onRejected), MDN上的解释如下:
onFulfilled 可选一个在此 Promise 对象被兑现时异步执行的函数。它的返回值将成为 then() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
valuePromise 对象的兑现值。
如果 onFulfilled 不是一个函数,则内部会被替换为一个恒等函数((x) => x),它只是简单地将兑现值向前传递。
onRejected 可选一个在此 Promise 对象被拒绝时异步执行的函数。它的返回值将成为 catch() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
reasonPromise 对象被拒绝的原因。
如果 onRejected 不是一个函数,则内部会被替换为一个抛出器函数((x) => { throw x; }),它会抛出它收到的拒绝原因
同时我们需要明确,then的返回是一个新的promise,因此我们有以下实现:
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
value = undefined
reason = undefined
construct(executor){
const reject = (val) => {
this.status = REJECTED
this.value = val
}
const resolve = (reason) => {
this.status = FULFILLED
this.reason = reason
}
try{
// 从这里我们可以知道new Promise(executor)中的executor是同步代码,会执行一次
executor(resolve, reject)
}catch(e){
reject(e)
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => (x)
onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
return new Promise((resolve, reject)=>{
})
}
}
then中的回调是在Promise发生改变的时候会调用的,因此我们肯定是要在Promise中判断相关的状态,我们补全这块代码,针对每种状态填写相应的逻辑,对于新的返回的新的Promise,我们也需要变更它的状态,因此有以下代码:
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
value = undefined
reason = undefined
construct(executor){
const reject = (val) => {
this.status = REJECTED
this.value = val
}
const resolve = (reason) => {
this.status = FULFILLED
this.reason = reason
}
try{
// 从这里我们可以知道new Promise(executor)中的executor是同步代码,会执行一次
executor(resolve, reject)
}catch(e){
reject(e)
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => (x)
onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
// 既然我们需要知道当前Promise的状态,我们就需要保存一个this变量
const self = this
return new Promse((resolve, reject)=> {
if(self.status === PENDING){
// 此时调用then的promise还未完成,因此需要将回调保存到队列中
}else if(self.status === FULFILLED){
// 此时调用then的promise已经完成,可以执行回调
}else if(self.status === REJECTED){
// 此时调用then的promise已经为拒绝状态,可以执行回调
}
})
}
}
从注释代码中我们可以知道,当PENDING的时候,我们需要保存这些回调函数,那么这些回调函数会在什么时候执行呢?在exectuor调用resolve()/reject()的时候,我们需要执行这些回调函数。所以在这之前,我们需要有地方能够存储这些回调。然后在resolve和reject的时候执行这些回调。
const FULFILLED = 'fullfilled'
const REJECTED = 'rejected'
const PENDING = 'pending'
class Promise{
status = PENDING
value = undefined
reason = undefined
resolvedCallbacks = []
rejectedCallbacks = []
construct(executor){
const reject = (reason) => {
this.status = REJECTED
this.reason = reason
if(rejectedCallbacks.length > 0){
setTimeout(()=>{
rejectedCallbacks.forEach((callback)=>{
callback(this.reason)
})
})
}
}
const resolve = (val) => {
this.status = FULFILLED
this.value = val
if(resolvedCallbacks.length > 0){
setTimeout(()=>{
resolvedCallbacks.forEach((callback)=>{
callback(this.value)
})
})
}
}
try{
// 从这里我们可以知道new Promise(executor)中的executor是同步代码,会执行一次
executor(resolve, reject)
}catch(e){
reject(e)
}
}
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => (x)
onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
// 既然我们需要知道当前Promise的状态,我们就需要保存一个this变量
const self = this
return new Promse((resolve, reject)=> {
if(self.status === PENDING){
// 此时调用then的promise还未完成,因此需要将回调保存到队列中
}else if(self.status === FULFILLED){
// 此时调用then的promise已经完成,可以执行回调
}else if(self.status === REJECTED){
// 此时调用then的promise已经为拒绝状态,可以执行回调
}
})
}
}
我们需要思考如何把回调函数推进callbacks数组中,我们不能直接把onFulfilled和onRejcted推进数组中,因为then返回的Promise的状态也需要改变,如果我们直接使用onFulfilled和onRejected,那么返回的then返回的Promise的状态可能一直都是PENDING的,无法被改变,因此我们需要一层包装函数,接受then返回的Promise中的resolve和reject,以此达到改变新Promise状态的目的。因此我们可以有以下实现:
// 只写then方法部分
then(onFulfilled, onRejected){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (x) => (x)
onRejected = typeof onRejected === 'function' ? onRejected : (x) => { throw x }
// 既然我们需要知道当前Promise的状态,我们就需要保存一个this变量
const self = this
return new Promse((resolve, reject)=> {
const handleFulfilled = (value) => {
try{
let res = onFulfilled(value)
resolve(res)
}catch(e){
reject(e)
}
}
const handleRejected = (reason) => {
try{
let res = onRejected(reason)
resolve(res)
}catch(e){
reject(e)
}
}
if(self.status === PENDING){
// 此时调用then的promise还未完成,因此需要将回调保存到队列中
this.resolvedCallbacks.push(handleFulfilled)
this.rejectedCallbacks.push(handleRejected)
}else if(self.status === FULFILLED){
// 此时调用then的promise已经完成,可以执行回调
setTimeout(()=>handleFulfilled(this.value))
}else if(self.status === REJECTED){
// 此时调用then的promise已经为拒绝状态,可以执行回调
setTimeout(()=>handleRejected(this.reason))
}
})
}
至此的话,简单的实现就差不多了,还差最后的关键,如果then中的回调返回的是一个Promise,我们该如何处理,then(()=>new Promise()).then(xxx)这种情况下,我们需要等待前一个then中的Promise完成,才能够执行下一个then。例子中()=>new Promise(),这个新建的Promise也就是我们onFulfilled方法的返回,也就是res。因此我们需要判断这个res是否为Promise,如果是Promise,需要等待这个Promise完成。
// 只写then方法部分
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (x) => x;
onRejected =
typeof onRejected === "function"
? onRejected
: (x) => {
throw x;
};
// 既然我们需要知道当前Promise的状态,我们就需要保存一个this变量
const self = this;
return new Promse((resolve, reject) => {
const handleFulfilled = (value) => {
try {
let res = onFulfilled(value);
if (res instanceof Promise) {
// 将我们现在的resovle和reject传递下去
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
};
const handleRejected = (reason) => {
try {
let res = onRejected(reason);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
};
if (self.status === PENDING) {
// 此时调用then的promise还未完成,因此需要将回调保存到队列中
this.resolvedCallbacks.push(handleFulfilled);
this.rejectedCallbacks.push(handleRejected);
} else if (self.status === FULFILLED) {
// 此时调用then的promise已经完成,可以执行回调
setTimeout(() => handleFulfilled(this.value));
} else if (self.status === REJECTED) {
// 此时调用then的promise已经为拒绝状态,可以执行回调
setTimeout(() => handleRejected(this.reason));
}
});
}
完整代码:
const FULFILLED = "fullfilled";
const REJECTED = "rejected";
const PENDING = "pending";
class Promise {
status = PENDING;
value = undefined;
reason = undefined;
resolvedCallbacks = [];
rejectedCallbacks = [];
construct(executor) {
const reject = (reason) => {
this.status = REJECTED;
this.reason = reason;
if (rejectedCallbacks.length > 0) {
setTimeout(() => {
rejectedCallbacks.forEach((callback) => {
callback(this.reason);
});
});
}
};
const resolve = (val) => {
this.status = FULFILLED;
this.value = val;
if (resolvedCallbacks.length > 0) {
setTimeout(() => {
resolvedCallbacks.forEach((callback) => {
callback(this.value);
});
});
}
};
try {
// 从这里我们可以知道new Promise(executor)中的executor是同步代码,会执行一次
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// 只写then方法部分
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (x) => x;
onRejected =
typeof onRejected === "function"
? onRejected
: (x) => {
throw x;
};
// 既然我们需要知道当前Promise的状态,我们就需要保存一个this变量
const self = this;
return new Promse((resolve, reject) => {
const handleFulfilled = (value) => {
try {
let res = onFulfilled(value);
if (res instanceof Promise) {
// 将我们现在的resovle和reject传递下去
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
};
const handleRejected = (reason) => {
try {
let res = onRejected(reason);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (e) {
reject(e);
}
};
if (self.status === PENDING) {
// 此时调用then的promise还未完成,因此需要将回调保存到队列中
this.resolvedCallbacks.push(handleFulfilled);
this.rejectedCallbacks.push(handleRejected);
} else if (self.status === FULFILLED) {
// 此时调用then的promise已经完成,可以执行回调
setTimeout(() => handleFulfilled(this.value));
} else if (self.status === REJECTED) {
// 此时调用then的promise已经为拒绝状态,可以执行回调
setTimeout(() => handleRejected(this.reason));
}
});
}
}
以上就是Promise的简单实现,其实我们也就主要实现了整体的架子和then方法,如果错误也请大家纠正哈。下一篇我们将继续实现resolve, reject, race,all这些方法.