用构造函数尝试实现,代码如下:
const [PENDING, FULFILLED, REJECTED] = ['pending', 'fulfilled', 'rejected']
function NewPromise(fn) {
this.state = PENDING
this.result = undefined
this.reason = undefined
this.resolvedCbs = []
this.rejectedCbs = []
const resolve = (val) => {
if(this.state === PENDING) {
this.state = FULFILLED
this.result = val
this.resolvedCbs.forEach(fn => fn())
}
}
const rejected = (val) => {
if(this.state === PENDING) {
this.state = REJECTED
this.reason = val
this.rejectedCbs.forEach(fn => fn())
}
}
try {
fn(resolve, rejected)
} catch (error) {
rejected(error)
}
}
NewPromise.prototype.then = function(onFulfilled, onRejected = (e) => { throw e }) {
return new NewPromise((resolve, reject) => {
if(!onFulfilled instanceof Function) {
onFulfilled = result => result
}
function handle(cb) {
try {
cb()
} catch (e) {
reject(e)
}
}
if(this.state === PENDING) {
this.resolvedCbs.push(() => {
handle(() => {
const r = onFulfilled(this.result)
resolve(r)
})
})
this.rejectedCbs.push(() => {
handle(() => {
const r = onRejected(this.reason)
resolve(r)
})
})
}
if(this.state === FULFILLED) {
handle(() => {
const r = onFulfilled(this.result)
resolve(r)
})
}
if(this.state === REJECTED) {
handle(() => {
const r = onRejected(this.reason)
resolve(r)
})
}
})
}
NewPromise.prototype.catch = function(onRejected) {
return this.then(undefined, onRejected)
}
NewPromise.prototype.all = function(cbs) {
let count = 0
const len = cbs.length
const arr = []
cbs.forEach((p => {
p.then((r) => {
arr.push(r)
count++
if(len === count) {
resolve(arr)
}
}).catch(e => {
reject(e)
})
}))
}
NewPromise.prototype.race = function(cbs) {
const len = cbs.length
cbs.forEach((p => {
p.then((r) => {
resolve(r)
}).catch(e => {
reject(e)
})
}))
}
执行试试,达到了预期效果,完美!
new NewPromise((resolve, reject) => {
console.log('in Promise...')
resolve(111)
}).then((val) => {
console.log('resolve👉', val)
}, (e) => {
console.log('rejected😖', e)
})
new NewPromise((resolve, reject) => {
console.log(11111111)
reject(1)
}).then((val) => {
console.log('resolve',val)
}).catch((e) => {
console.log('reject', e)
})
const p1 = new NewPromise((resolve, reject) => {
reject(1)
})
const p2 = new NewPromise((resolve, reject) => {
resolve(2)
})
p1.then((val) => {
console.log('resolve1',val)
}).catch((e) => {
console.log('reject1', e)
})
p2.then((val) => {
console.log('resolve2',val)
}).catch((e) => {
console.log('reject2', e)
})
还有一种版本是 class写法的,相比构造函数会难写些。
class MyPromise {
constructor (fn) {
this.state = 'pending'
this.value = undefined
let resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
}
}
let reject = value => {
if (this.state === 'pending') {
this.state = 'rejected'
this.value = value
}
}
// 自动执行函数
try {
fn(resolve, reject)
} catch (e) {
reject(e)
}
}
// then
then(onFulfilled, onRejected) {
switch (this.state) {
case 'fulfilled':
onFulfilled(this.value)
break
case 'rejected':
onRejected(this.value)
break
default:
onRejected(this.value);
}
}
}
这边判断了 state === pending ,是因为防止 多个 resolve 、多个 reject 或 resolve 和 reject 混用时,会执行多次回调。
# 如果不加判断,以下所有的resolve和reject都会执行,返回值为最后一个回调值。
if (this.state === 'pending') {}
new MyPromise((resolve, reject) => {
console.log('in Promise...')
resolve(111)
resolve(222)
reject(333)
})
如有不足,请指出!🤝
©2018-2020 hongshali.com 版权所有 ICP证:闽ICP备18029655号-1