/**
* promise 原理
*
* 1. exector
* 需要传递一个执行函数exector参数,用于执行何时进行状态改变的逻辑
* 这个函数需要两个参数 resovle, reject 分别用于处理成功、失败的状态改变
*
* 2. status
* status 状态
* 仅可以通过内部的resolve、reject内置函数进行修改,且仅当status == 'pending'状态可以被修改,状态一旦确定就无法被再次修改
* resolve、reject都会接收一个参数,并分别保存在data和reason中
*
* 3. then 方法
* then 方法主要用于监听成功或者失败的回调
* 接收两个参数resovleHandle、和rejectHandle函数用于处理成功、失败时的回调
* 每个then函数仅会执行其中一个函数 成功或者失败,主要由status来判断
* 且resovleHandle、和rejectHandle会自动传入内部保存的对应的数据data和reason
* 若执行器内的状态改变涉及异步操作时,then方法实际处于pending的状态
* 异步处理
* 此时我们如果希望在特定的时刻执行then方法传递的resovleHandle、和rejectHandle,我们则需要对他们进行缓存,并在希望调用的时候调用(resolve, reject)
* cache: {resolveHandle: [], rejectHandle: []},由于可能会有多个then方法的监听,所以这两个cache是数组
*
* 4. then 方法的链式调用
* 1. 链式调用的核心是then方法返回一个新的promise,并将then方法内的主要逻辑放在新promise的exector内执行,这是为了后面的一个步骤做准备
* 2. 新的promise的then会接收上一个promise的then方法resolveHandle和rejectHandle返回的值
* 3. 处理then方法未传递回调函数的防错机制
* 4. 仅当上一个promise函数或者then内部逻辑发生错误的时候会触发下一个then方法的reject回调
* 5. 若then的回调返回的是一个VPromise实例,我们需要立刻执行该promise的then方法,并在对应的回调中调用我们新的promise的状态函数
* 6. 内部代码执行错误捕获机制,为then方法和exector函数内进行try/catch机制来捕获错误
*
*/
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class VPromise {
constructor(exector) {
// promise状态
this.status = PENDING
// 成功数据
this.data = undefined
// 失败原因
this.reason = undefined
// 回调缓存3
this.cache = {
resovleHandle: [],
rejectHandle: []
}
// 执行执行器
try {
exector(this.resolve, this.reject)
} catch (error) {
this.reject(error.message || error)
}
}
// 成功时执行操作
resolve = (v) => {
let {
status,
cache
} = this
// 判断status状态
if (status !== PENDING) return
// 修改状态为成功
this.status = FULFILLED
// 存储成功
this.data = v
// 执行特殊的异步回调
if (cache && cache.resovleHandle) {
while (cache.resovleHandle.length > 0) {
let handle = cache.resovleHandle.pop()
handle && handle(this.data)
}
}
}
// 失败时执行操作
reject = (v) => {
let {
status, cache
} = this
// 判断status状态
if (status !== PENDING) return
// 修改状态为失败
this.status = REJECTED
// 存储失败原因
this.reason = v
// 执行特殊的异步回调
if (cache && cache.rejectHandle) {
while (cache.rejectHandle.length > 0) {
let handle = cache.rejectHandle.pop()
handle && handle(this.reason)
}
}
}
// 设置回调缓存
setCache(res, rej) {
res && this.cache.resovleHandle.push(res)
rej && this.cache.rejectHandle.push(rej)
}
// then方法监听成功或失败操作
then(resovleHandle = v => v, rejectHandle = e => {
throw e
}) {
let promise = new VPromise((res, rej) => {
// then方法主要运行逻辑
if (this.status === FULFILLED) {
let value = resovleHandle(this.data)
// 为了将value传递给then方法的回调,我们可以传递给res,间接传递给then
// 执行res,不仅可以传递参数,还可以开启下一个promis的执行
// res(value)
asyncHandle(value, res, rej)
} else if (this.status === REJECTED) {
// console.log('error: ' + this.reason)
let error = rejectHandle(this.reason)
// 同上
asyncHandle(error, res, rej)
} else {
// 异步有点不同
this.setCache((data) => {
try {
let value = resovleHandle(data)
asyncHandle(value, res, rej)
} catch (error) {
rej(error.message || error)
}
}, (reason) => {
try {
let error = rejectHandle(reason)
asyncHandle(error, res, rej)
} catch (error) {
rej(error.message || error)
}
})
}
})
return promise
}
// 并行操作all
static all(arrary = []) {
let result = []
let count = 0
return new VPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
count++
if (count === arrary.length) {
resolve(result)
}
}
for (let i = 0; i < arrary.length; i++) {
let res = arrary[i]
if (res instanceof VPromise) {
// 是promise
res.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
addData(i, res)
}
}
})
}
// finally 方法,不管promise的状态是什么都会执行finally传递的函数,并且可以链式调用
finally(fn) {
// 若fn的返回值是promise,需要等待该promise执行完成在向下执行
return this.then((data) => {
return VPromise.resolve(fn()).then(() => data)
}, (reason) => {
return VPromise.resolve(fn()).then(() => {
throw reason
}, () => {
throw reason
})
})
}
catch(reject) {
return this.then(undefined, reject)
}
// resolve方法,返回一个新的状态为resolve方法
static resolve(data) {
// 判断是否是promise对象
// 是直接返回
if (data instanceof VPromise) return data
// 否则返回一个状态为fulfilled的promise对象
return new VPromise((resolve) => resolve(data))
}
// reject方法,返回一个新的状态为reject方法
static reject(data) {
// 判断是否是promise对象
// 是直接返回
if (data instanceof VPromise) return data
// 否则返回一个状态为rejected的promise对象
return new VPromise((resolve, reject) => reject(data))
}
}
// 用于处理promise和非promise的情况
function asyncHandle(value, res, rej) {
if (value instanceof VPromise) {
// 说明是promise
// 执行promise的then方法来判断何是执行res或reject
// 并将then方法回调中的传入值作为下一个promise的参数值
value.then((data) => {
res(data)
}, (err) => {
rej(err)
})
} else {
// 否则是普通值
res(value)
}
}
let promise = new VPromise((res, rej) => {
// res(1)
// rej('c023-error')
// a()
setTimeout(() => {
// res('success')
rej('fail...')
}, 1000)
})
注:本文章仅用于学习与总结,如有疑问欢迎交流