要写一个Promise,首先从使用他开始
乞丐版
let p = new Promise((resolve,reject)=>{
// resolve('ok')
setTimeout(()=>resolve('ok'), 100)
})
p.then(res=>{
console.log(res) // ok
},(err)=>{
console.log(err)
})
我们的关注点在于,p.then和resolve的执行顺序是不定的 (通常我们会做一篮子异步操作后再resolve出去)
那么不管它们的执行顺序是怎样的,我们需要保证最终then中的回调正常触发。
先来完成乞丐版的编写
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class _P {
constructor(fn) {
this.status = PENDING
this.value = null
this.err = null
this.fulfilledArr = []
this.rejectArr = []
this.resolve = (value) => {
// pending状态 ,扭转为fulfilled
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value // 保存参数,用于then的
// 执行fulfilled中的所有回调
this.fulfilledArr.forEach(cb => {
cb(value)
})
}
}
this.reject = (value) => {
// pending状态 ,扭转为reject
if (this.status === PENDING) {
this.status = REJECTED
this.value = value // 保存参数,用于then的
// 执行fulfilled中的所有回调
this.rejectArr.forEach(cb => {
cb(value)
})
}
}
try {
fn(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
}
_P.prototype.then = function (onFulfilled, onReject) {
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onReject(this.err)
}
if (this.status === PENDING) {
this.fulfilledArr.push(() => {
onFulfilled(this.value)
})
this.rejectArr.push(() => {
onReject(this.err)
})
}
}
要点:
构造Promise时,,会执行传入的回调函数,假设:
1.构造函数中我们没有做异步,且很快的resolve或reject(假设此时then还没运行),那么在resolve/reject中执行回调列表时,会发现没有函数可能执行,但status已经扭转,当后续then执行的时候,根据状态执行对应的回调,
2.构造函数中做了异步,导致then回调是先执行的,这时就会命中 if(this.status === PENDING) ,将回调函数塞到对应的任务队列中,当构造中的异步函数执行完,开始执行resolve / reject时,回调列表 列表就可以被执行了
链式调用
链式调用即在then方法中需要返回一个promise, 这里有分为两种情况
p.then(res => {
return 'hello'
return Promise.resolve('hello')
}).then(res => {
console.log(res) // hello
})
我们在then中可以返回一个Promise或常量,而我们希望下一个then可以正常接收到"hello"
返回常量
用递归即可,const res = onFulfilled(this.value), 把结果resolve出去即可
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class _P {
constructor(fn) {
this.status = PENDING
this.value = null
this.err = null
this.fulfilledArr = []
this.rejectArr = []
this.resolve = (value) => {
// pending状态 ,扭转为fulfilled
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value // 保存参数,用于then的
// 执行fulfilled中的所有回调
this.fulfilledArr.forEach(cb => {
cb(value)
})
}
}
this.reject = (value) => {
// pending状态 ,扭转为reject
if (this.status === PENDING) {
this.status = REJECTED
this.value = value // 保存参数,用于then的
// 执行fulfilled中的所有回调
this.rejectArr.forEach(cb => {
cb(value)
})
}
}
try {
fn(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
}
_P.prototype.then = function (onFulfilled, onReject) {
let next = new _P((resolve, reject) => {
if (this.status === FULFILLED) {
const res = onFulfilled(this.value)
resolve(res)
}
if (this.status === REJECTED) {
const res = onReject(this.value)
resolve(res)
}
if (this.status === PENDING) {
// 如果状态还是PENDING,把事件装进回调数组
this.fulfilledArr.push(() => {
const res = onFulfilled(this.value)
resolve(res)
})
this.rejectArr.push(() => {
const res = onReject(this.err)
reject(res)
})
}
})
return next
}
返回Promise
..to be continue