let status = { //promise默认有三种状态
pending: 'pending', //进行中
fulfilled: 'fulfilled', //成功
rejected: 'rejected' //失败
}
function resolvePromise(promise2, x, resolve, reject) {} //这个是为了考虑的全面点,如果then返回了new promise
class promise { //new的时候会传参,这个参数会默认给到constructor中
constructor(excutor) {
this.status = 'pending' //给到一个默认状态
this.value = '' //成功的时候将传递的值赋值到上面
this.reason = '' //失败的时候将传递的值赋值到上面
this.onResolveCallBacks = [] //在then中收集成功的回调函数,因为then中状态还是pending不会调用这个回调
this.onRejectedCallBacks = [] //在then中收集失败的后的处理,因为then中状态还是pending不会调用这个回调
const resolve = (value) => { //一般我们在调用resolve的时候都会传出去一个值
if (this.status = status.pending) { //如果调用了resolve,判断下当前是否进行中,
//进行中的话将状态改成完成态
this.status = status.fulfilled //完成态
this.value = value //之所以保存这个是为了调用then方法的时候将这个传递进去
this.onResolveCallBacks.forEach(item => item()) //如果这个数组不为空说明这个方法是异步的,需要等到回调的值有值了再去执行所以代码在this.value后面
}
}
const reject = (value) => {
if (this.status = status.pending) { //不管调用reject还是resolve都需要是进行中的状态
this.status = status.rejected //调用失败函数更改状态值
this.reason = value //保存下,如果调用catch的话将失败的值返回出去
this.onRejectedCallBacks.forEach(item => item())
}
}
executor(resolve, reject) //这个是executor是用户写的时候传递的参数,我们调用它,将定义的resolve,和reject传进去
//一般new promise的时候 new promise((resolve,reject,) => { 这里可以做自己的一些处理程序})
}
then(onFulfilled, onRejected) { //then方法,一般是回调的时候使用,里面的额参数类比我们接口使用时response => {}传入的这个函数
//因为每次调用then方法都会产生一个新的promise,所以这个内部还需要去new promise
let promise2 = new promise((resolve, rejected) => {
if (this.status === status.fulfilled) { //成功的话
try {
let x = onFulfilled(this.value) //那就是执行用户传入的那个函数然后把之前resovle出来的this.value传入,如果有返回值的话那么我们需要取出来,作为下一次继续then的参数值
resolve(x) //这样执行的话我们又把x赋值到this.value上了,下一次onFulfilled可以把上一次的值传入
} catch (e) {
reject(e)
}
}
if (this.status === status.rejected) { //失败的话
try {
let x = onRejected(this.reason) //执行传入的函数传入失败的值
resolve(x) //如果是执行的错误方法,那就把它sesolve放到value上作为下一次的参数值
} catch (e) {
rejected(e)
}
}
if (this.status === status.pending) { //如果执行then方法的时候还是pending状态(异步的先在还不能执行 onFulfilled,拿不到上一步的回调)那就将当前then后
//的回调存起来,所以我们在类中还需要申明两个数组
this.onResolveCallBacks.push(() => {
try {
let x = onFulfilled(this.value) //将成功后的处理塞入数组相当于订阅
resolve(x) //将这个值存入value作为下一次then的值
} catch (e) {
reject(e)
}
})
this.onRejectedCallBacks.push(
() => {
try {
let x = onFulfilled(this.reason) //将失败后的处理塞入数组相当于订阅
resolve(x) //将这个值存入value作为下一次then的值
} catch (e) {
reject(e)
}
}
)
}
})
return promise2
}
all(promises) { //all方法是一个静态方法,因为promise.all(){}.then 可以then所以内部是一个new promise
return new promise((resolve, reject) => {
let arrValue = [] //什么一个数组去储存所有的返回值
let index = 0
function keepProcess(i, value) {
arrValue[i] = value
if (++index === promises.length) { //当标识的数字跟promise的长度一样说明执行完毕了把结构resolve出去
resolve(arrValue)
}
}
//这个时候需要判断下传入的数组是不是promise,循环数组因为我们需要并发所以我们使用for循环
for (let i = 0; i < promises.length; i++) {
if (typeof promises[i] === 'function') { //判断当前是否是promise还是普通值
promises[i].then(res => { //如果是promise还需要执行把结果传过去
keepProcess(i, res)
})
} else {
keepProcess(i, promises[i])
}
}
})
}
race(promises) { //race的意思是赛跑哪个跑得快就用谁的,传入多个promises,哪个先执行完使用谁的,其他的也会执行只是不会采用结果
new promise((resolve, reject) => { //内部还是包装成一个promise,因为下面要使用它的resolve,依靠resolve去获取第一个执行完的值
for (let i = 0; i < promises.length; i++) {
if (typeof promises[i] === 'function') {
promises[i].then(resolve) //之前一直没理解,看了下then方法,这个resolve会作为onFulfilled去执行,resolve中会改变pend状态,那么外部的new promise就会把这个值产出,使用then时候就可以获取到
} else {
resolve(promises[i]) //如果是普通类型也直接产出
}
}
})
}
}
let p = new Promise((resolve, reject) => { //利用race,实现立即中断promise为失败状态
setTimeout(() => { //这里申明一个promise
resolve('成功');
}, 3000);
})
function wrap(p){ //一个wrap函数
let abort;
let p1 = new Promise((resolve,reject)=>{ //再申明一个promise,将reject方法保存到一个变量上
abort = reject;
});
let newPromise = Promise.race([p1,p]) //传入之前的两个promise,在race中
newPromise.abort = abort //rece里面存储一个reject方法
return newPromise
}
let p1 = wrap(p); //这个拿到的p1就是promise.race,可以在后面.then
p1.then(data => {
console.log('success', data)
}, err => {
console.log('error', err)
})
setTimeout(() => {
p1.abort('超过2s了');
}, 2000);
//总结就是p这个promise设置了个延时器3s,p1promise只是保存了reject,没有resolve或者reject,那么我们在外部可以设置个定时器2s模拟下,2s就调用reject这样程序就停止了
Promise.prototype.finally = function (callback) { //finally方法
return this.then((data)=>{
return Promise.resolve(callback()).then(()=>data)
},(err)=>{
return Promise.resolve(callback()).then(()=>{throw err})
})
}
//finally方法是无论如何都会执行,那么它内部本质就是一个then方法,然后取到上一次的结果data传入,还需要考虑后面还需要接着then,那么它内部还会再去promise。resolve()产出保存上一次的结果,然后then就能拿到