- Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
- Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
- pending -> fulfilled
- pending -> rejected
- 一旦状态确定就不可更改
- resolve和reject函数是用来更改状态的
- resolve: fulfilled
- reject: rejected
- then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的
- then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
- 同一个promise对象下面的then方法是可以被调用多次的
- then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
// 三个状态等待 成功 失败
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
class MyPromise {
//constructor接收执行器(即promise传递过来的回调函数,立即执行)
constructor (executor) {
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
//promise状态,默认为等待
status = PENDING;
value = undefined; // 成功后传递的值
reason = undefined; //失败后传递的原因
successCallbackArr = []; // then方法成功回调数组
failCallbackArr = []; // then方法失败回调数组
resolve = value => {
//判断状态,如果是等待,则可以向下执行
if( this.status !== PENDING ) return
//将状态更改为成功
this.status = FULFILLED;
//保存成功之后的值
this.value = value;
// 判断成功回调是否存在,存在就调用
while(this.successCallbackArr.length) this.successCallbackArr.shift()()
}
reject = reason => {
//判断状态,如果是等待,则可以向下执行
if( this.status !== PENDING ) return
//将状态更改为失败
this.status = REJECTED;
//保存失败后的原因
this.reason = reason;
// 判断失败回调是否存在,存在就调用
while(this.failCallbackArr.length) this.failCallbackArr.shift()()
}
//then方法定义在原型对象上,判断promise状态,根据成功还是失败,执行不同的回调
then (successCallback, failCallback) {
successCallback = successCallback ? successCallback : value => value //如果then方法不传参数(回调),则执行value => value,将value传递给下一个then
failCallback = failCallback ? failCallback : reason => { throw reason } // 例如:promise.then().then().then(value => console.log(value))
let promise2 = new Promise((resolve, reject) => { //为了能够链式调用,then方法需要返回一个promise对象
if( this.status === FULFILLED ){ // 成功状态
setTimeout(()=>{ // 为了获取到promise2,先让promise2执行完,所以将这段代码变为异步代码,当主任务执行完毕后执行
try {
let x = successCallback(this.value)
// 判断X的值是普通值,还是promise对象
// 如果是普通值,则直接调用resolve
// 如果是promise对象,查看Ppromise对象返回的结果
// 再根据promise对象返回的结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
},0)
} else if( this.status === REJECTED ){ //失败状态
setTimeout(()=>{ // 为了获取到promise2,先让promise2执行完,所以将这段代码变为异步代码,当主任务执行完毕后执行
try {
let x = failCallback(this.reason)
// 判断X的值是普通值,还是promise对象
// 如果是普通值,则直接调用resolve
// 如果是promise对象,查看Ppromise对象返回的结果
// 再根据promise对象返回的结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
},0)
} else { //等待状态
//将成功回调和失败回调存储起来
this.successCallbackArr.push(()=>{
setTimeout(()=>{ // 为了获取到promise2,先让promise2执行完,所以将这段代码变为异步代码,当主任务执行完毕后执行
try {
let x = successCallback(this.value)
// 判断X的值是普通值,还是promise对象
// 如果是普通值,则直接调用resolve
// 如果是promise对象,查看Ppromise对象返回的结果
// 再根据promise对象返回的结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
},0)
})
this.failCallbackArr.push(()=>{
setTimeout(()=>{ // 为了获取到promise2,先让promise2执行完,所以将这段代码变为异步代码,当主任务执行完毕后执行
try {
let x = failCallback(this.reason)
// 判断X的值是普通值,还是promise对象
// 如果是普通值,则直接调用resolve
// 如果是promise对象,查看Ppromise对象返回的结果
// 再根据promise对象返回的结果,决定调用resolve还是reject
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
},0)
})
}
})
return promise2
}
finally (callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all (arr) {
let result = [];
let index = 0; //防止传来的promise中的方法是异步的,如果是异步的,会输出空值,因为for循环结束的时候,异步操作可能都没有执行呢
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value;
index++
if( index === arr.length ){
resolve(result)
}
}
for ( let i=0; i<arr.length; i++ ) {
let current = arr[i];
if(current instanceof MyPromise){
//promise对象
current.then(value => addData(i, value), reason => reject(reason))
}else{
//普通值
addData(i,arr[i])
}
}
})
}
static resolve (value) {
if( value instanceof MyPromise) return value
return new MyPromise( resolve => resolve(value) )
}
}
function resolvePromise (promise2, x, resolve, reject) {
if( promise2 === x ) { //防止返回自身promise对象
return reject(new TypeError('error'))
}
if (x instanceof MyPromise) {
//promise对象
x.then(resolve, reject) //等价于 x.then(value => resolve(value), reason => reject(reason))
}else {
//普通值
resolve(x) //将上一个then执行的值,通过resolve传给下一个then方法
}
}
module.exports = MyPromise;