一、promise实现
核心要点
- Promise是微任务
- 链式调用
class MyPromise {
static PENDING = 'PENDING'
static FULFILED = 'FULFILED'
static REJECTED = 'REJECTED'
constructor(callback) {
if (typeof callback !== 'function') {
throw new TypeError('promise resolve undefined is no a function')
}
this.status = MyPromise.PENDING
this.value = null
this.resolveQueues = []
this.rejuectQueues = []
callback(this._resolve.bind(this), this._reject.bind(this))
}
_resolve(val) {
//通过 window.postMessage 实现微任务
window.addEventListener('message', () => {
if (this.status !== MyPromise.PENDING) return
this.value = val
this.status = MyPromise.FULFILED
let handleFun = this.resolveQueues.shift()
if (handleFun) {
handleFun(this.value)
}
})
window.postMessage('')
}
_reject(val) {
window.addEventListener('message', () => {
if (this.status !== MyPromise.PENDING) return
this.value = val
this.status = MyPromise.REJECTED
let handleFun = this.rejuectQueues.shift()
if (handleFun) {
handleFun(this.value)
}
})
window.postMessage('')
}
then(resolveFun, rejectFun) {
// 再次递归调用MyPromise以实现链式调用
return new MyPromise((resolve, reject) => {
// 将resolveFun和resolve同时放入队列中,使调用时按顺序输出
function resolveHandle(val) {
if (typeof resolveFun === 'function') {
let result = resolveFun(val)
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} else {
resolve(val)
}
}
function rejectHandle(val) {
if (typeof rejectFun === 'function') {
let result = rejectFun()
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
reject(result)
}
reject(err)
} else {
reject(val)
}
}
this.resolveQueues.push(resolveHandle)
this.rejuectQueues.push(rejectHandle)
})
}
catch(rejectFun) {
this.then(undefined, rejectFun)
}
}
new MyPromise((resolve, reject) => {
resolve(1)
}).then((val) => {
console.log('then1', val)// 先输出then1 1
return 2
}).then((val) => {
console.log('then2', val)// 再输出then2 2
})
二、promise.all 实现
static all(iterator){
let len = iterator.length;
let n = 0;
let result= [];
return new AlleyPromise((resolve,reject)=>{
iterator.forEach((item, index)=>{
item.then((val)=>{
++n;
result[index] = val
if(len === n) {
resolve(result);
}
}).catch((e)=>{
reject(e);
})
})
}
三、promise.race 实现
static race(iterator){
return new AlleyPromise((resolve,reject)=>{
iterator.forEach((item)=>{
item.then((val)=>{
resolve(val);
}).catch((e)=>{
reject(e);
})
})
})
}
四、promise.resolve 实现
static resolve(val){
return new AlleyPromise((resolve)=>{
resolve(val)
})
}
五、promise.reject 实现
static reject(val){
return new AlleyPromise((resolve,reject)=>{
reject(val)
})
}
六、完整方法
class MyPromise {
static PENDING = 'PENDING'
static FULFILED = 'FULFILED'
static REJECTED = 'REJECTED'
constructor(callback) {
if (typeof callback !== 'function') {
throw new TypeError('promise resolve undefined is no a function')
}
this.status = MyPromise.PENDING
this.value = null
this.resolveQueues = []
this.rejuectQueues = []
callback(this._resolve.bind(this), this._reject.bind(this))
}
_resolve(val) {
//通过 window.postMessage 实现微任务
window.addEventListener('message', () => {
if (this.status !== MyPromise.PENDING) return
this.value = val
this.status = MyPromise.FULFILED
let handleFun = this.resolveQueues.shift()
if (handleFun) {
handleFun(this.value)
}
})
window.postMessage('')
}
_reject(val) {
window.addEventListener('message', () => {
if (this.status !== MyPromise.PENDING) return
this.value = val
this.status = MyPromise.REJECTED
let handleFun = this.rejuectQueues.shift()
if (handleFun) {
handleFun(this.value)
}
})
window.postMessage('')
}
then(resolveFun, rejectFun) {
// 再次递归调用MyPromise以实现链式调用
return new MyPromise((resolve, reject) => {
// 将resolveFun和resolve同时放入队列中,使调用时按顺序输出
function resolveHandle(val) {
if (typeof resolveFun === 'function') {
let result = resolveFun(val)
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} else {
resolve(val)
}
}
function rejectHandle(val) {
if (typeof rejectFun === 'function') {
let result = rejectFun()
if (result instanceof MyPromise) {
result.then(resolve, reject)
} else {
reject(result)
}
reject(err)
} else {
reject(val)
}
}
this.resolveQueues.push(resolveHandle)
this.rejuectQueues.push(rejectHandle)
})
}
catch(rejectFun) {
this.then(undefined, rejectFun)
}
static all(iterator){
let len = iterator.length;
let n = 0;
let result= [];
return new AlleyPromise((resolve,reject)=>{
iterator.forEach((item, index)=>{
item.then((val)=>{
++n;
result[index] = val
if(len === n) {
resolve(result);
}
}).catch((e)=>{
reject(e);
})
})
}
static race(iterator){
return new AlleyPromise((resolve,reject)=>{
iterator.forEach((item)=>{
item.then((val)=>{
resolve(val);
}).catch((e)=>{
reject(e);
})
})
})
}
static resolve(val){
return new AlleyPromise((resolve)=>{
resolve(val)
})
}
static reject(val){
return new AlleyPromise((resolve,reject)=>{
reject(val)
})
}
}