手写Promise
手写Promise
分析:
- promise是一个类, 传入参数是回调函数(执行器),函数会立即执行
- promise有三种状态,分别是等待 PENDING 成功 FULFILLED 失败RJECKTED,且一旦由pending转为另外两种状态之后不得更改
- 在执行器中调用 resolve 和reject函数是用来更改状态的 从pending-> fulfilled 或者从pending-> rejected
- 传递给resolve 就是成功传递的值 , 传给reject的就是失败的原因
- then 方法内部做的事情就是判断状态 成功的话调用成功的回调函数,失败的话调用失败的回调函数,另外then方法是promise原型对象上的方法
- 当前状态为等待就是异步的时候我们不知道执行失败还是成功 ,所以把失败和成功的回调函数保存起来,在 resolve和rekect中判断 失败回调和成功回调是否有,存在就执行并传参
- then方法的链式调用每个都要返回一个proimise对象, 和把上一个返回值给下一个then方法
- then中不能返回当前的promise对象,会导致promise对象的循环调用
// 5. 定义 promise的3中状态为常量 这三种状态的值不会改变了所以定义为常量
const PENDING = 'penging';
const FULFILLED = 'fulfilled';
const RJECKTED = 'rejected';
// 定义一个MyPromise的类
class MyPromise {
// 接收执行器
constructor(exector) {
// 立即调用执行器,并传递两个回调函数的参数 resolve,reject
exector(this.resolve, this.reject)
}
status = PENDING // 设置初始状态为PENDING
// 定义成功的参数 和失败的原因
value = undefined; // 成功后的值
reason = undefined; // 失败后的值
// successCallcack = undefined // 保存成功回调函数
// failCallback = undefined // 保存失败回调函数
successCallcack = [] // 链式保存成功回调函数数组
failCallback = [] // 链式保存失败回调函数数组
// 定义 resolve,reject 定义为箭头函数的原因是想让内部this的指向指向MyPromise对象 因为这两个函数是直接调用的
resolve = value => {
// 判断状态是否是等待 等待的话就return
if (this.status ==== PENDING) return
//更改为成功状态
this.status = FULFILLED
// 保存成功之后的值
this.value = value
// 判断成功是否保存了成功回调函数,保存了就执行并传参
// this.successCallcack && this.successCallcack(this.value)
// 当前成功的回调还有成功回调就继续执行并删除 直到数组中没有成功的回调函数
while (this.successCallcack.length) this.successCallcack.shift()()
}
reject = (reason) => {
// 判断状态是否是等待 等待的话就return
if (this.status ==== PENDING) return
// 更改为失败状态
this.status = RJECKTED
// 保存失败后的原因
this.reason = reason
// 判断失败是否保存了失败回调函数,保存了就执行并传参
// this.failCallback = this.failCallback(this.reason)
// 当前失败的回调还有成功回调就继续执行并删除 直到数组中没有失败的回调函数
while (this.failCallback.length) this.failCallback.shift()(this.reason)
}
// promise的实例上有一个then方法 接收两个参数 成功和失败的回调函数
then(successCallcack, failCallback) {
successCallcack = successCallcack ? successCallcack : value => value
failCallback = failCallback ? failCallback : reason => {
throw reason
}
// 返回promise对象实现链式调用
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 13成功 调用成功回调 并传给函数成功的值
setTimeout(() => {
try {
let x = successCallcack(this.value)
// 传递给下个then方法的回调函数
// 如果当前的x 是普通值就传给下个对象,如果是promise对象就查看返回结果 根据结果判断调用resolve还是reject
// resolve(x)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.status === RJECKTED) {
// 失败 调用失败回调 并传给函数失败的原因
setTimeout(() => {
try {
let y = failCallback(this.reason)
// 传递给下个then方法的回调函数
reject(y)
} catch (error) {
reject(error)
}
}, 0)
} else {
// 处理异步 等待的状态的将失败或成功的回调保存起来
// this.successCallcack = successCallcack
// this.failCallback = failCallback
// 多个异步then的链式编程所以successCallcack和failCallback应该是个数组
// this.successCallcack.push(successCallcack)
// this.failCallback.push(failCallback)
//等待
this.successCb.push(() => {
setTimeout(() => {
try {
let x = successCb(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
});
this.failCb.push(() => {
setTimeout(() => {
try {
let x = failCb(this.err)
resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
});
}
})
return promise2
// . 链式编程中 then 中调用成功和失败的回调函数
}
// 其他方法
catch (cb) {
return this.then(undefined, cb)
} finally(cb) {
return this.then(value => {
return MyPromise.resolve(cb()).then(() => value);
}, err => {
return MyPromise.resolve(cb()).then(() => {
throw err
})
})
}
// 静态方法all
static all(arr) {
let result = [];
let index = 0;
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) {
current.then(value => addData(i, value), err => reject(err))
} else {
addData(i, arr[i])
}
}
})
}
// 静态方法resolve
static resolve(value) {
// 判断传进来的value是不是属于MyPrimise对象 属于返回value 不属于返回一个新的MyPromise对象
if (value instanceof MyPromise) {
return value
} else {
return new MyPromise((resolve) => resolve(value))
}
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 返回重复引用的错误
if (promise2 === x) {
return reject(new TypeError('重复引用了'))
}
if (x instanceof MyPromise) {
// x属于MyPromise对象调用then方法返回 resolve, reject
// x.then(value => resolve(value), reason => reject(reason)))
// 优化
x.then(resolve, reject)
} else {
resolve(x)
}
}
// module.export(MyPromise)
// 测试代码
let promise = new MyPromise((resolve, reject) => {
// 正常调用传参
resolve('成功')
// reject('失败')
// 处理异步
// setTimeout(() => {
// resolve('成功')
// }, 2000)
// 处理多个then的异步
// setTimeout(() => {
// resolve('成功')
// }, 2000)
})
// 1. 可以成功的输出成功失败 也验证了状态一旦由pending更改为fulfilled之后不能改为rejected
// 2. 等待两秒后输出成功
// promise.then(value => {
// console.log(value);
// }, reason => {
// console.log(reason);
// })
// promise.then(value => {
// console.log(value);
// }, reason => {
// console.log(reason);
// })
// promise.then(value => {
// console.log(value);
// }, reason => {
// console.log(reason);
// })
// function other() {
// return new MyPromise((resolve, reject) => {
// resolve('other')
// })
// }
// promise.then(value => {
// console.log(value);
// return other()
// }, reason => {
// console.log(reason);
// })
// function p1() {
// return new MyPromise((resolve) => {
// setTimeout(() => {
// resolve('p1')
// }, 2000)
// })
// }
// function p2() {
// return new MyPromise((resolve) => {
// resolve('p2')
// })
// }
// p2().finally(()=>{
// console.log('finally');
// }).then(res=>{
// console.log(res);
// },err=>{
// console.log(err);
// })
// MyPromise.all(['a', 'b', p1(), p2(), 'c']).then(res => {
// console.log(res);
// })
// MyPromise.resolve(100).then(res => console.log(res))
// function other() {
// return new MyPromise((resolve, reject) => {
// resolve('other')
// })
// }
// 当前promise对象重复调用
// let p1 = promise.then(value => {
// // throw new Error('自定义then错误')
// console.log(value);
// // return p1;
// }, err => {
// console.log(err);
// return 1000
// })