本文: 手写实现PromiseA+规范以及Promise(原型,静态,额外扩展等)方法,没错,来吧~~~
手写Promise(符合PromiseA + 规范)
const FULFILLED = 'fulfilled', REJECTED = 'rejected', PENDING = 'pending'
class Promise_ {
constructor(excutor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.resolveList = []
this.rejectList = []
const resolve = value => {
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.resolveList.forEach(fn => fn(value))
}
}
const reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.rejectList.forEach(fn => fn(reason))
}
}
try {
excutor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(resolveFn, rejectFn) {
typeof resolveFn !== 'function' && (resolveFn = value => value)
typeof rejectFn !== 'function' && (rejectFn = reason => { throw reason })
let bridgePromise
return bridgePromise = new Promise_((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = resolveFn(this.value)
resolvePromise(x, bridgePromise, resolve, reject)
} catch (error) {
reject(error)
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = rejectFn(this.reason)
resolvePromise(x, bridgePromise, resolve, reject)
} catch (error) {
reject(error)
}
});
}
if (this.status === PENDING) {
this.resolveList.push(value => {
setTimeout(() => {
try {
const x = resolveFn(value)
resolvePromise(x, bridgePromise, resolve, reject)
} catch (error) {
reject(error)
}
});
})
this.rejectList.push(reason => {
setTimeout(() => {
try {
const x = rejectFn(reason)
resolvePromise(x, bridgePromise, resolve, reject)
} catch (error) {
reject(error)
}
});
})
}
})
}
}
function resolvePromise(x, bridgePromise, resolve, reject) {
if (x === bridgePromise) return reject(new TypeError('circle'))
if (x !== null && (typeof x === 'function' || typeof x === 'object')) {
let called = false
try {
const then = x.then
if (typeof then === 'function') {
then.call(x,
y => {
if (called) return
called = true
resolvePromise(y, bridgePromise, resolve, reject)
},
error => {
if (called) return
called = true
reject(error)
}
)
} else {
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
1,实现Promise.prototype.catch
Promise_.prototype.catch = function (callback) {
return this.then(null, callback)
}
2,实现Promise.prototype.finally
Promise_.prototype.finally = function (callback) {
return this.then(
v => Promise_.resolve(callback()).then(() => v),
err => Promise_.resolve(callback()).then(() => { throw err })
)
}
3,实现Promise.resolve
Promise_.resolve = function (val) {
return new Promise_(resolve => resolve(val))
}
4,实现Promise.reject
Promise_.reject = function (err) {
return new Promise_((resolve, reject) => reject(err))
}
5,实现Promise.all
Promise_.all = function (list) {
let res = [], count = 0
return new Promise_((resolve, reject) => {
list.forEach((p, i) => {
p.then(v => {
res[i] = v; ++count >= list.length && resolve(res)
}).catch(reject)
})
})
}
6,实现Promise.race
Promise_.race = function (list) {
return new Promise_((resolve, reject) => list.forEach(p => p.then(resolve).catch(reject)))
}
7,实现Promise.allSettled
Promise_.allSettled = function (list) {
let res = [], count = 0
return new Promise_(resolve => {
list.forEach((p, i) => {
p.then(v => {
res[i] = { status: 'fulfilled', value: v }; ++count >= list.length && resolve(res)
}).catch(err => {
res[i] = { status: 'rejected', reason: err }; ++count >= list.length && resolve(res)
})
})
})
}
8,实现Promise.retry:指定请求重试次数,重试次数内完成则完成,否则失败
Promise_.retry = function (request, count) {
let rejectCount = 0
return new Promise_((resolve, reject) => {
function step() {
request().then(resolve).catch(err => ++rejectCount < count ? step() : reject(err))
}
step()
})
}
9,实现Promise.series:串行执行所有返回Promise请求(类似tabable中AsyncSeriesHook)
Promise_.series = function (list, ...args) {
let i = 0
return new Promise_((resolve, reject) => {
function step(fn) {
fn().then(v => ++i < list.length ? step(list[i].bind(null, v)) : resolve(v)).catch(reject)
}
step(list[i].bind(null, ...args))
})
}
10,实现Promise.maxRun:指定Promise请求最大并发数量,所有成功,则返回所有请求结果,如果某请求失败,则返回该失败结果
Promise_.maxRun = function (list, max) {
let i = 0, maxCount = 0, res = [], count = 0;
return new Promise_((resolve, reject) => {
function step() {
for (; i < list.length && maxCount < max; i++ , maxCount++) {
const idx = i
list[idx]().then(
v => {
res[idx] = v; count++; maxCount--;
if (count >= list.length) resolve(res)
else maxCount < max && step()
}
).catch(reject)
}
}
step()
})
}