手写promise
1、基础用法
此步暂时只解决了调用一次then(不支持链式调用)
const PENDING = 'PENDING',
FULFILLED = 'FULFILLED',
REJECTED = 'REJECTED'
class BasePromise {
constructor(executor) {
this.status = PENDING
this.value = undefined
this.reason = undefined
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
resolve(value) {
if (this.status === PENDING) {
this.value = value
this.status = FULFILLED
this.onResolvedCallbacks.forEach((fn) => {
fn(this.value)
})
}
}
reject(reason) {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
this.onRejectedCallbacks.forEach((fn) => {
fn(this.reason)
})
}
}
// 这里只能处理包含一个then方法,并接收两个参数onFulfilled, onRejected
then(onFulfilled, onRejected) {
// 成功提交
if (this.status === FULFILLED) {
onFulfilled(this.value)
} else if (this.status === REJECTED) {
// 失败提交
onRejected(this.reason)
} else if (this.status === PENDING) {
// 如果promise的状态是PENDING,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再依次执行对应的函数
this.onResolvedCallbacks.push(() => {
this.value = onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
this.reason = onRejected(this.reason)
})
}
}
catch() {}
}
2、扩展 实现 catch 和 then 方法 支持链式调用
缺陷 不支持then中 return promise 的类别
class FullPromise extends BasePromise {
constructor(executor) {
super(executor)
}
// 重写基类的方法
then(onFulfilled, onRejected) {
// 解决onFulfilled, onRejected没有传值的问题
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v
// 因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后then的resolve中捕获
onRejected =
typeof onRejected === 'function'
? onRejected
: (error) => {
throw error
}
// 异步执行,放到下一步
return new FullPromise((resolve, reject) => {
if (this.status === PENDING) {
// 加入 回调方法
this.onResolvedCallbacks.push((value) => {
try {
let result = onFulfilled(value)
resolve(result)
} catch (error) {
reject(error)
}
})
this.onRejectedCallbacks.push((value) => {
try {
let result = onRejected(value)
resolve(result)
} catch (error) {
reject(error)
}
})
} else if (this.status === FULFILLED) {
setTimeout(() => {
try {
let result = onFulfilled(this.value)
resolve(result)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败提交
setTimeout(() => {
try {
let result = onRejected(this.reason)
resolve(result)
} catch (error) {
reject(error)
}
}, 0)
}
})
}
catch(onRejected) {
onRejected =
typeof onRejected === 'function'
? onRejected
: (error) => {
return error
}
return new FullPromise((resolve, reject) => {
if (this.status === REJECTED) {
// 失败提交
setTimeout(() => {
try {
let result = onRejected(this.reason)
resolve(result)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === PENDING) {
this.onRejectedCallbacks.push((value) => {
try {
let result = onRejected(value)
resolve(result)
} catch (error) {
reject(error)
}
})
}
})
}
}
3、缩减冗余代码 + 支持then和catch中返回promise类型
首先 根据上面重复代码整合了以下成工具方法的使用
function parse(origin, fn, val, resolve, reject) {
let flag = 0
try {
let result = fn(val)
if (result === origin) {
flag = 1
throw new Error('same key')
}
if (result instanceof FullPromise) {
result.then(resolve, reject)
} else {
resolve(result)
}
} catch (error) {
console.log(error)
if (flag === 0) {
reject(error)
}
}
}
then 和 catch 的使用
// 重写基类的方法
then(onFulfilled, onRejected) {
// 解决onFulfilled, onRejected没有传值的问题
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (v) => v
// 因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后then的resolve中捕获
onRejected =
typeof onRejected === 'function'
? onRejected
: (error) => {
throw error
}
// 异步执行,放到下一步
let origin = new FullPromise((resolve, reject) => {
if (this.status === PENDING) {
// 加入 回调方法
this.onResolvedCallbacks.push((value) => {
parse(origin, onFulfilled, value, resolve, reject)
})
this.onRejectedCallbacks.push((value) => {
parse(origin, onRejected, value, resolve, reject)
})
} else if (this.status === FULFILLED) {
setTimeout(() => {
parse(origin, onFulfilled, this.value, resolve, reject)
}, 0)
} else if (this.status === REJECTED) {
// 失败提交
setTimeout(() => {
parse(origin, onRejected, this.reason, resolve, reject)
}, 0)
}
})
return origin
}
catch(onRejected) {
this.onRejectedCallbacks = []
let onFulfilled = (v) => v
onRejected =
typeof onRejected === 'function'
? onRejected
: (error) => {
return error
}
let origin = new FullPromise((resolve, reject) => {
if (this.status === REJECTED) {
// 失败提交
setTimeout(() => {
parse(origin, onRejected, this.reason, resolve, reject)
}, 0)
} else if (this.status === PENDING) {
this.onResolvedCallbacks.push((value) => {
parse(origin, onFulfilled, this.value, resolve, reject)
})
this.onRejectedCallbacks.push((value) => {
parse(origin, onRejected, value, resolve, reject)
})
} else if (this.status === FULFILLED) {
console.log('catche FULFILLED:' + this.value)
parse(origin, onFulfilled, this.value, resolve, reject)
}
})
return origin
}