题记
之前跟着课程写过一个promise,这次来实习培训,老师让我们学习promise相关的知识,我就想着上次已经把一些基本用法学的差不多了,但是原理什么的只能说有点印象,所以这次决定再写一次,看看两次下来能不能有新体会,希望能把promise原理彻底理清。
开写
首先完成了MyPromise类的构建,以及基本的异步功能。 即 new MyPromise(resolve, reject).then(value => {}, reason => {})这样的功能,诸如链式调用,Promise.all这样的特性和方法在后面完善。
const PENDING = 'PENDING'
const FULFILLED = 'RESOLVE'
const REJECTED = 'REJECT'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch(e) {
this.reject(e)
}
}
status = PENDING
value = undefined
reason = undefined
successCallback = null
failCallback = null
resolve(value) {
if(this.status !== PENDING) return
this.status = FULFILLED
this.value = value
this.successCallback && this.successCallback(this.value)
}
reject(reason) {
if(this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
this.failCallback && this.failCallback(this.reason)
}
then(successCallback, failCallback) {
this.successCallback = successCallback ? successCallback: value => value
this.failCallback = failCallback ? failCallback: reason => { throw reason }
switch(this.status) {
case FULFILLED: {
this.successCallback(this.value)
}
case REJECTED: {
this.failCallback(this.reason)
}
}
}
}
进阶版:接下来对这个基本功能的promsie进行改进,可以接收多个回调函数,可以进行链式调用
const PENDING = 'PENDING'
const FULFILLED = 'RESOLVE'
const REJECTED = 'REJECT'
class MyPromise {
constructor(executor) {
try {
executor(this.resolve.bind(this), this.reject.bind(this))
} catch(e) {
this.reject(e)
}
}
status = PENDING
value = undefined
reason = undefined
successCallbackQueue = []
failCallbackQueue = []
resolve(value) {
if(this.status !== PENDING) return
this.status = FULFILLED
this.value = value
while(this.successCallbackQueue.length > 0) {
this.successCallbackQueue.shift()(this.value)
}
}
reject(reason) {
if(this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
while(this.successCallbackQueue.length > 0) {
this.failCallbackQueue.shift()(this.reason)
}
}
then(successCallback,failCallback){
successCallback = successCallback ? successCallback:value => value
failCallback = failCallback ? failCallback:reason => {throw reason}
let newPromise = new MyPromise((resolve,reject) =>{
switch(this.status) {
case FULFILLED: {
setTimeout(() => {
let x = successCallback(this.value)
this.handlePromise(x,resolve,reject)
},0)
} break
case REJECTED: {
setTimeout(() => {
let x = failCallback(this.reason)
this.handlePromise(x,resolve,reject)
},0)
}break
case PENDING: {
this.successCallbackQueue.push(() => {
setTimeout(() => {
let x = successCallback(this.value)
this.handlePromise(x,resolve,reject)
},0)
})
this.failCallbackQueue.push(() => {
setTimeout(() => {
let x = failCallback(this.reason)
this.handlePromise(x,resolve,reject)
},0)
})
}break
}
})
return newPromise
}
handlePromise(x, resolve, reject) {
if(x instanceof MyPromise) {
x.then(value => resolve(value),reason => reject(reason))
} else {
resolve(x)
}
}
}
终极版:完成了promise的基本功能后,可以为我的promsie类增加一些静态方法了,这些方法可以让我的promise更加顺手。我新增了Promise.all, Promise.race, Promise.finall 等方法
static all(promiseArray) {
return new MyPromise((resolve, reject) => {
let count = promiseArray.length
const res = []
while(promiseArray.length > 0) {
const x = promiseArray.shift()
if(x instanceof MyPromise) {
x.then(value => {
res.push(value)
count--
if(count === 0) resolve(res)
}, reason => {
reject(reason)
})
} else {
res.push(x)
count--
if(count === 0) resolve(res)
}
}
})
}
static race(promiseArray) {
return new MyPromise((resolve, reject) => {
const res = []
while(promiseArray.length > 0) {
const x = promiseArray.shift()
if(x instanceof MyPromise) {
x.then(value => {
resolve(value)
}, reason => {
reject(reason)
})
}
}
})
}
static resolve(n) {
if(n instanceof MyPromise) return n
return new MyPromise(resolve => resolve(n))
}
finally(callback){
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
},reason => {
return MyPromise.resolve(callback()).then(() => reason)
})
}