规范的步骤很详细,但是可能不懂规范书写方式的话,看起来可能有些困难。
前置知识
promise 有三种状态 pending fulfilled rejected
一旦状态改变就不可逆
pending ---> fulfilled resolve
pending --- rejected rejected
OK 了解前置知识后可以开始了
首先 对应两种状态,成功的时候我们称它的值为value 失败的时候也会有对应的reason
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
let resolve = (value) => {
this.state = 'fulfilled' // 状态变更resolve
this.value = value
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
}
executor(resolve, reject)
}
}
然后我们实现then , then接收两个参数onFulfilled 、onRejected,
- 当状态为成功 则执行onFulfilled
- 否则执行onRejected
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
let resolve = (value) => {
this.state = 'fulfilled' // 状态变更resolve
this.value = value
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
}
executor(resolve, reject)
}
// +++++++++++++++++++++
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value)
} else if (this.state === 'rejected') {
onRejected(this.reason)
}
}
}
至此,面对同步的逻辑,是可以完美运行的,但是碰到异步代码还有点招架不住,因为异步代码的状态不是立即确定的,所以我们需要等待它执行完后再确定。
所以,我们需要添加两个数组,分别存储成功和失败的回调,等到状态改变后执行,同时在then的penging状态 下向回调中添加任务
class myPromise {
constructor(executor) {
this.state = 'pending'
this.value = undefined
this.reason = undefined
this.onResolveCallbacks = [] // +++
this.onRejectCallbacks = [] // +++
let resolve = (value) => {
this.state = 'fulfilled' // 状态变更resolve
this.value = value
this.onResolveCallbacks.forEach(fn => fn())// +++
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
this.onRejectCallbacks.forEach(fn => fn())// +++
}
executor(resolve, reject)
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value)
} else if (this.state === 'rejected') {
onRejected(this.reason)
} else { // ++++++++++++++++++++
this.onResolveCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
这时候我们碰到setTimeout这种异步任务也可以执行了,但是如果有返回值或返回的结果是一个promise,我们这时候还无法进行链式调用,我们来看一下规范:
为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2:promise2 = new Promise((resolve, reject)=>{})
将这个promise2返回的值传递到下一个then中
如果返回一个普通的值,则将普通的值传递给下一个then中
当我们在第一个then中return了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
- 首先,要看x是不是promise。
- 如果是promise,则取它的结果,作为新的promise2成功的结果
- 如果是普通值,直接作为promise2成功的结果 所以要比较x和promise2
- resolvePromise的参数有promise2(默认返回的promise)、x(我们自己return的对象)、resolve、reject resolve和reject是promise2的
then(onFulfilled, onRejected) {
// 为了实现链式调用,我们必须返回一个promise
let promise2 = new myPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
let x = onFulfilled(this.value) //获取返回值
resolvePromise(promise2, x, resolve, reject) //判断返回值的类型
} else if (this.state === 'rejected') {
let x = onRejected(this.reason) //获取返回值
resolvePromise(promise2, x, resolve, reject) //判断返回值的类型
} else {
this.onResolveCallbacks.push(() => {
let x = onFulfilled(this.value) //获取返回值
resolvePromise(promise2, x, resolve, reject) //判断返回值的类型
})
this.onRejectCallbacks.push(() => {
let x = onRejected(this.reason) //获取返回值
resolvePromise(promise2, x, resolve, reject) //判断返回值的类型
})
}
})
return promise2
}
实现resolvePromise
秘籍规定了一段代码,让不同的promise代码互相套用,叫做resolvePromise
如果 x === promise2,则是会造成循环引用,自己等待自己完成,则报“循环引用”错误
let p = new Promise(resolve => {
resolve(0);
});
var p2 = p.then(data => {
// 循环引用,自己等待自己完成,一辈子完不成
return p2;
})
1、判断x
Otherwise, if x is an object or function,Let then be x.then
- x 不能是null
- x 是普通值 直接resolve(x)
- x 是对象或者函数(包括promise),let then = x.then
2、当x是对象或者函数(默认promise)
- 声明了then
- 如果取then报错,则走reject()
- 如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调
- 如果成功的回调还是pormise,就递归继续解析
3、成功和失败只能调用一个 所以设定一个called来防止多次调用
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
return reject(new TypeError("Chain cycle detected"))
}
let called
if (typeof x !== null && (typeof x === 'object' || typeof x === 'function')) { //如果返回值是promise
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, v => {
if (called) return;
called = true
resolve(v)
resolvePromise(promise2, v, resolve, reject)
}, r => {
if (called) return;
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (error) {
if (called) return;
called = true
reject(error)
}
} else { //如果是普通值
resolve(x)
}
}

then(onFulfilled,onRejected) { // onFulfilled如果不是函数,就忽略onFulfilled,直接返回value onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; // onRejected如果不是函数,就忽略onRejected,直接扔出错误 onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }; let promise2 = new Promise((resolve, reject) => { if (this.state === 'fulfilled') { // 异步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'rejected') { // 异步 setTimeout(() => { // 如果报错 try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }; if (this.state === 'pending') { this.onResolvedCallbacks.push(() => { // 异步 setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0); }); this.onRejectedCallbacks.push(() => { // 异步 setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }, 0) }); }; }); // 返回promise,完成链式 return promise2; } }