1. 基本功能实现
思路:(当前不考虑链式调用)
- promise 实例化时 会传入一个函数,此函数有俩个参数
- 直接执行这个传入的函数
- 根据这两个参数(函数),去改变函数的状态,并且储存传递的值
- 调用方法时(.then),根据当前 promise 的状态去做不同的操作
- 调用 .then 时,如果是 resolve 或者 reject 状态, 则直接异步执行当前传入的函数(.then中的函数);
如果是 pending 状态,则当前 promise 没有执行 resolve 或者 reject 函数(可能是异步执行),所以将 .then 传入的函数,推入 promise 的数组中(订阅发布),并且在状态改变时,依次执行数组中的函数。
// 初始化状态
const PENDING = 'pending'
const RESOLVE = 'resolve'
const REJECT = 'reject'
// 初始化 Promise
class myPromise {
// Promise 初始化的结果,可以理解为 resolve 或者 reject 的参数
reason = undefined;
result = undefined;
// 储存当前 Promise 的状态, 只有完成 进行 失败 三种状态
status = PENDING;
// 订阅 .then 方法传来的函数,所有.then 传来的参数都会存在此数组中
onResolvedArr = [];
// 订阅 .catch 方法传来的函数,所有.catch 传来的参数都会存在此数组中
onRejectedArr = [];
constructor (excution) {
/**
* 定义 resolve 以及 reject 函数
* 改变状态并且储存传入的参数
* 注意: 只有是 PENDING 才会执行 resolve 或者 reject 函数
*/
const resolve = (result) => {
console.log(80, status)
if (this.status === PENDING) {
this.status = RESOLVE
this.result = result
this.onResolvedArr.map(func => func()) // 发布执行被订阅的函数
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECT
this.reason = reason
this.onRejectedArr.map(func => func()) // 发布执行被订阅的函数
}
}
excution(resolve, reject) // 实例化时 直接执行传入的函数
}
// then 方法接收 onResolved, onRejected 两个函数作为参数
then(onResolved, onRejected) {
// 使用 setTimeout 是为了将传入的函数变为异步任务
if (this.status === RESOLVE) {
setTimeout(() => {
onResolved(this.result)
})
}
if (this.status === REJECT) {
setTimeout(() => {
onRejected(this.reason)
})
}
/**
* 如果状态为 PENDING, 则代表 resolve 或者 reject 没有执行
* 所以将当前的函数 推入数组中,在 resolve 或者 reject, 再遍历数组并执行里面的函数
*/
if (this.status === PENDING) {
this.onResolvedArr.push(() => {
onResolved(this.result)
})
this.onRejectedArr.push(() => {
onRejected(this.reason)
})
}
}
}
2. 链式调用实现
上面实现了promise 的基本功能,但是还不能链式调用,需要再改造一下
思路:
- then 方法中返回一个新的 promise 对象
- 接收 onResolved 函数的返回值,并且使用 resolve 返回他,以此达到链式调用
注意: onResolved 函数的返回值不能为一个 promise 对象。如果是,则做特殊处理 (递归)
// 简写方式
then(onResolved, onRejected) {
const newPromise = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
// 接收 onResolved 的返回值,并调用 resolve
const newPromiseRes = onResolved(this.result)
resolve(newPromiseRes)
})
}
if (this.status === REJECTED) {
setTimeout(() => {
const newPromiseRes = onRejected(this.reason)
reject(newPromiseRes)
})
}
if (this.status === PENDING) {
this.onResolvedArr.push(() => {
const newPromiseRes = onResolved(this.result)
resolve(newPromiseRes)
})
this.onRejectedArr.push(() => {
const newPromiseRes = onRejected(this.reason)
reject(newPromiseRes)
})
}
})
// 新创建 Promise 实例,并且返回,实现链式调用
return newPromise
}
注意: 如果 onResolved() 返回的是一个 Promise ,那么就会达不到我们链式调用的效果。所以就要将 promise 递归成非 promise 类型
定义 handlePromise 方法来处理 onResolved 的返回值
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
// promise 返回值的处理函数
const handlePromise = (newPromiseRes, newPromise, resolve, reject) => {
// 返回值不能返回自己,否则抛出错误
if (newPromiseRes === newPromise) {
throw new Error('can not return oneself')
}
/**
* 1. 结果是否为 object(new Promise()) 或者 function(Promise)
* 2. 如果是,则进入判断是否为 promise, 否则直接 resolve 结果。
*/
if (
(typeof newPromiseRes === 'object' && newPromiseRes !== null)
|| typeof newPromiseRes === 'function'
) {
// 若 then 方法为一个函数,则认为此数据是一个 promise。否则直接 resolve 结果
const then = newPromiseRes['then']
if (typeof then === 'function') {
/**
* 直接执行 then 方法,并且递归,直到它的 r 参数不是一个 promise
* 若有异常,则直接 reject 传递
*/
then.call(
newPromiseRes,
(r) => {
handlePromise(r, newPromise, resolve, reject)
},
(e) => {
reject(e)
}
)
} else {
resolve(newPromiseRes)
}
} else {
resolve(newPromiseRes)
}
}
// promise 类
class myPromise {
// Promise 初始化的结果,可以理解为 resolve 或者 reject 的参数
reason = undefined;
result = undefined;
// 储存当前 Promise 的状态, 只有完成 进行 失败 三种状态
status = PENDING;
// 订阅 .then 方法传来的函数,所有.then 传来的参数都会存在此数组中
onResolvedArr = [];
// 订阅 .catch 方法传来的函数,所有.catch 传来的参数都会存在此数组中
onRejectedArr = [];
constructor (excution) {
/**
* 定义 resolve 以及 reject 函数
* 改变状态并且储存传入的参数
* 注意: 只有是 PENDING 才会执行 resolve 或者 reject 函数
*/
const resolve = (result) => {
if (this.status === PENDING) {
this.status = FULFILLED
this.result = result
this.onResolvedArr.map(func => func()) // 发布执行被订阅的函数
}
}
const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.onRejectedArr.map(func => func()) // 发布执行被订阅的函数
}
}
excution(resolve, reject) // 实例化时 直接执行传入的函数
}
// then 方法接收 onResolved, onRejected 两个函数作为参数
then(onResolved, onRejected) {
const newPromise = new myPromise((resolve, reject) => {
// 使用 setTimeout 是为了将传入的函数变为异步任务
if (this.status === FULFILLED) {
setTimeout(() => {
const newPromiseRes = onResolved(this.result)
handlePromise(newPromiseRes, newPromise, resolve, reject)
})
}
if (this.status === REJECTED) {
setTimeout(() => {
const newPromiseRes = onRejected(this.reason)
handlePromise(newPromiseRes, newPromise, resolve, reject)
})
}
/**
* 如果状态为 PENDING, 则代表 resolve 或者 reject 没有执行
* 所以将当前的函数 推入数组中,在 resolve 或者 reject, 再遍历数组并执行里面的函数
*/
if (this.status === PENDING) {
this.onResolvedArr.push(() => {
const newPromiseRes = onResolved(this.result)
handlePromise(newPromiseRes, newPromise, resolve, reject)
})
this.onRejectedArr.push(() => {
const newPromiseRes = onRejected(this.reason)
handlePromise(newPromiseRes, newPromise, resolve, reject)
})
}
})
// 新创建 Promise 实例,并且返回,实现链式调用
return newPromise
}
catch (onRejected) {
const s = data => data
const c = (err) => {
throw new Error(err)
}
return this.then(s, onRejected || c)
}
}
一个基本的 promise 功能就实现了,
以上代码未做完整的错误异常处理,只能按规则(入参必须都传)取调用。