- promise就是一个类
在执行类的时候需要传递一个执行器进去,执行器会立即执行- Promise中有三种状态,分别为成功-fulfilled 失败-rejected 等待-pending
pending -> fulfilled
pending -> rejected
一旦状态确定就不可更改- resolve 和 reject函数是用来更改状态的
resolve:fulfilled
reject:rejected- then方法内部做的事情就是判断状态
如果状态是成功,调用成功回调函数
如果状态是失败,就调用失败回调函数
then方法是被定义在原型对象中的- then成功回调有一个参数,表示成功之后的值;then失败回调有一个参数,表示失败后的原因
// 1. 用常量定义 promise 三种状态, 能有提示
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
constructor(executor) {
// 捕获执行器(executor)代码执行异常时的错误
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// status 存储 promise 状态
status = PENDING;
// value 存成功的值
value = undefined;
// reason 存失败提示
reason = undefined;
// 为异步调用,存储成功回调。(数组形式为多次调用 .then 方法时依次存储其回调函数)
successCallback = [];
// 为异步调用,存储失败回调。(数组形式为多次调用 .then 方法时依次存储其回调函数)
failCallback = [];
// 2. 定义 resolve 成功方法
resolve = (value) => {
// 判断 promise 状态,pending 时继续执行
if (this.status !== PENDING) return;
// 修改 premiere 状态为成功,用于后续判断
this.status = FULFILLED;
// 保存成功的值
this.value = value;
// 循环调用多次.then的回调函数,直到清空所有的回调函数
while (this.successCallback.length) {
return this.successCallback.shift()();
}
};
// 3. 定义 reject 失败方法
reject = (reason) => {
// 判断 promise 状态,pending 时继续执行
if (this.status !== PENDING) return;
// 修改 premiere 状态为成功,用于后续判断
this.status = REJECTED;
// 保存成功的值
this.reason = reason;
// 循环调用多次.then的回调函数,直到清空所有的回调函数
while (this.failCallback.length) {
return this.failCallback.shift()();
}
};
// 4. 定义 then 方法
then(successCallback, failCallback) {
// then 方法参数可选
successCallback = successCallback ? successCallback : value => value;
failCallback = failCallback ? failCallback : reason => { throw reason };
// then 方法返回一个promise对象
let thenPromise = new MyPromise((resolve, reject) => {
// 判断 promise 状态
if (this.status === FULFILLED) {
// 因为new Promise需要执行完成之后才有thenPromise,同步代码中没有thenPromise
// 使用异步操作拿到 thenPromise
setTimeout(() => {
// 如果回调中报错的话就执行reject
try {
// 创建一个变量接收 successCallback的返回值
let callbackValue = successCallback(this.value)
// 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
// 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
// 如果是其他值 则调用 resolve() 返回
// 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
// 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
resolvePromise(thenPromise, callbackValue, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 如果回调中报错的话就执行reject
try {
// 创建一个变量接收 failCallback的返回值
let callbackValue = failCallback(this.reason)
// 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
// 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
// 如果是其他值 则调用 resolve() 返回
// 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
// 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
resolvePromise(thenPromise, callbackValue, resolve, reject) // [1] 被调方法1
} catch (error) {
reject(error)
}
}, 0)
} else {
// 异步情况,promise 进入等待,状态不变
// 将成功、失败的回调存起来
this.successCallback.push(() => {
setTimeout(() => {
// 处理异步的成功错误情况
// 如果回调中报错的话就执行reject
try {
// 创建一个变量接收 failCallback的返回值
let callbackValue = successCallback(this.value)
// 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
// 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
// 如果是其他值 则调用 resolve() 返回
// 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
// 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
resolvePromise(thenPromise, callbackValue, resolve, reject) //[1] 被调方法1
} catch (error) {
reject(error)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
// 处理异步的成功错误情况
// 如果回调中报错的话就执行reject
try {
// 创建一个变量接收 successCallback的返回值
let callbackValue = failCallback(this.reason)
// 调用 resolvePromise 判断 callbackValue 的值是 promise对象 还是 其他值
// 如果是promise对象 查看 promsie对象 返回的结果,再根据 promise对象 返回的结果 决定调用resolve 还是调用reject
// 如果是其他值 则调用 resolve() 返回
// 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
// 所以要给 resolvePromise 传递 4个参数,thenPromise,callbackValue, resolve, reject
resolvePromise(thenPromise, callbackValue, resolve, reject) // [1] 被调方法1
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return thenPromise
}
// 5. 定义原型对象上的 finally 方法
finally(callback) {
// 不论是否成功都要调用 callback函数
// 所以调用 then 方法获取 promise 状态,并返回其结果
return this.then(
(value) => {
// 如果callback是一个异步的promise对象,我们还需要等待其执行完毕,
// 需要用到静态方法resolve,把callback()调用之后返回的promise对象传递过去,并且执行promise,且在成功之后返回value
return MyPromise.resolve(callback()).then(() => value)
},
// 失败之后调用的then方法,然后把失败的原因返回出去。
(reason) => {
return MyPromise.resolve(callback().then(() => { throw reason }))
}
)
}
// 6. 定义 catch 方法
// 只接收错误回调
catch (failCallback) {
// 在内部调用 then 方法,成功回调位置传 undefined
return this.then(undefined, failCallback)
}
// 7. 静态方法 all
static all(array) {
// 创建一个数组接收结果
let result = [];
// 创建一个计数器,确保结果数组的个数与接收的一致
let num = 0
// all 返回一个promise对象
return new MyPromise((resolve, reject) => {
// 创建一个方法,将所有的成功返回值都放入 result 数组
function addItem(index, value) {
result[index] = value
num++
// 当计数器与接收的数组长度一致时,证明一件处理完毕,输出结果数组result
if (num === array.length) {
resolve(result)
}
}
// 遍历接收数组的每一项
for (let i = 0; i < array.length; i++) {
let item = array[i]
// 判断当前项是否为 promise 对象
if (item instanceof MyPromise) {
// 如果是 promise对象,则调用 then 方法处理取得结果
item.then((value) => addItem(i, value), (reason) => reject(reason))
} else {
// 如果为其他值则直接加入结果数组
addItem(i, item)
}
}
})
}
// 8. 创建 resolve 静态方法
static resolve(value) {
// resolve 方法返回 promise对象
// 判断接收的值时否为 promise对象,是则直接返回,不是则将接收值放入promise中返回
if (value instanceof MyPromise) {
return value
}
return new MyPromise((resolve) => resolve(value))
}
}
// [1] 被调方法1 resolvePromise()
// 因为Mypromise 在成功、失败、异步都需要处理 callBack 返回值,
// 所以创建一个 resolvePromise 专门处理 callbackValue 相关的问题
function resolvePromise(thenPromise, callbackValue, resolve, reject) {
// 需要判断then之后return的promise对象和原来的是不是一样的,判断 callbackValue 和 thenPromise 是否相等
if (thenPromise === callbackValue) {
// 如果相等了,说明return的是自己,抛出类型错误并返回
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
// 判断succValue 是否为 MyPromise 的实例对象
if (callbackValue instanceof MyPromise) {
// 如果是 promise 对象
callbackValue.then(value => resolve(value), reason => reject(reason));
// 可简写为下式
// callbackValue.then(resolve, reject)
} else {
// 如果是其他值resolve返回
resolve(callbackValue)
}
}
module.exports = MyPromise;