關(guān)于Promise是什么,不做贅述。
屬性
首先一個(gè)Promise類,要有如下屬性:
- status: pending resolved/fulfilled rejected
- result
實(shí)例方法
- then 返回一個(gè)promise實(shí)例,參數(shù)是兩個(gè)回調(diào)函數(shù),當(dāng)狀態(tài)轉(zhuǎn)變?yōu)閞esolved時(shí),執(zhí)行第一個(gè)回調(diào)函數(shù),當(dāng)狀態(tài)轉(zhuǎn)變?yōu)閞ejected時(shí),執(zhí)行第二個(gè)回調(diào)函數(shù)
- catch 傳入一個(gè)回調(diào)函數(shù),相當(dāng)于then方法傳入的第二個(gè)參數(shù)
- finally
靜態(tài)方法
- all
- race
實(shí)現(xiàn)
首先我們看一下Promise是怎么使用的
new Promise((resolve, reject) => {
setTimeout(() => resolve, 100)
})
可以看出Promise對(duì)象在創(chuàng)建實(shí)例時(shí)就要執(zhí)行傳入其構(gòu)造函數(shù)的方法A,維護(hù)實(shí)例的狀態(tài),并且要重新封裝resolve和reject方法,替代A,以便第一時(shí)間獲取狀態(tài)更新。
構(gòu)造函數(shù)
function MyPromise(executor) {
this.status = 'pending'
this.result = null
const resolve = (data) => {
if (this.status !== 'pending') {
return
}
this.state = 'resolved'
this.result = data
while (this.onResolvedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()()
this.onRejectedCallbacks.shift()
}
}
const reject = (data) => {
if (this.status !== 'pending') return
this.status = 'rejected'
this.result = data
while (this.onRejectedCallbacks.length > 0) {
this.onResolvedCallbacks.shift()
this.onRejectedCallbacks.shift()()
}
}
executor(resolve, reject)
}
then
MyPromise.prototype.then = function (onResolved, onRejected) {
// 如果傳入?yún)?shù)不是函數(shù),為其初始化為空函數(shù)
onResolved = typeof onResolved === 'function' ? onResolved : ()=>{}
onRejected = typeof onRejected === 'function' ? onRejected : ()=>{}
return new MyPromise((resolve, reject) => {
// this指向執(zhí)行then方法的MyPromise實(shí)例
if(this.status === 'resolved') {
let res = onResolved(this.result) // then方法的返回值
resolve(res) // 傳遞給下一個(gè)then
}
if(this.status === 'rejected' && onRejected) {
let err = onRejected(this.result)
reject(err)
}
// 說明前一步還沒有完成,先保存兩個(gè)回調(diào),等待完成后再執(zhí)行
if(this.status === 'pending') {
this.onResolvedCallbacks.push(()=>{
let res = onResolved(this.result)
resolve(res)
})
this.onRejectedCallbacks.push(()=>{
let err = onRejected(this.result)
reject(err)
})
}
})
}
catch
MyPromise.prototype.catch = function (onRejected) {
if (this.status === 'rejected') {
onRejected(this.result)
}
if (this.status === 'pending') {
this.onResolvedCallbacks.push(() => {})
this.onRejectedCallbacks.push(() => {
onRejected(ths.result)
})
}
}
all
MyPromise.prototype.all = function (promiseArrary) {
const values = []
let count = 0
return new MyPromise((resolve, reject) => {
promiseArray.forEach((p, index) => {
p = p instanceof MyPromise ? p : new MyPromise((resolve, reject) => resolve(p))
p.then(
(value) => {
count++
values[index] = value
if (count === promiseArray.length) {
resolve(values)
}
},
(err) => reject(error)
)
})
})
}
race
MyPromise.prototype.race = function(promiseArray) {
return new Promise((resolve, reject) => {
promiseArray.forEach((p, index) => {
p = p instanceof Promise ? p : new Promise((resolve, reject) => resolve(p))
p.then(value => {
resolve(value)
}, err => reject(err))
})
})
}