import { isFunction } from "util";
const PANDING = 'panding'
const RESOLVE = 'resolve'
const REJECT = 'reject'
function MyPromise(dosth) {
// 状态标识
let status = PANDING
// 用来存储回调方法,因为支持链式then,所以用数组存储多个回调
let resolveCallback = []
let rejectCallback = []
this.value = null
// 思路:一次次迭代,逐步完善
/**
* 1、实现基本功能:
* * then存储回调
* * reslove和reject执行回调
* * 执行异步操作
* 2、控制状态
* 3、then链式调用
* 4、回调在执行栈执行完之后才执行
* 5、 串行promise 当前promise达到resolve状态后才开始下一个promise
*/
// 实现resolve和reject
function resolve (res) {
// 异步函数需要在执行栈主流程执行完之后才可以开始执行
setTimeout(() => {
// 只有状态为panding才可以改变状态
if (status === PANDING ) {
// 执行回调方法
status = RESOLVE
that.value = res
resolveCallback.forEach(cb => {
cb(that.value)
})
}
}, 0);
}
function reject (err) {
setTimeout(() => {
if (status === PANDING) {
status = REJECT
that.value = err
rejectCallback.forEach(cb => {
cb(that.value)
})
}
}, 0);
}
// 执行异步操作
try{
dosth()
} catch(err) {
reject(err)
}
}
// 实现then方法
MyPromise.prototype.then = function (onResolve, onReject) {
const that = this
// 串行promise: 当前Promise执行完毕后执行下一个promise
// 这里用resolve2 和reject2 表示该处两个方法属于下方新的myPromise,暂时称为promise2,方法中用到的变量也属于promise2
let myPromise2 = new MyPromise((resolve2, reject2) => {
/**
*
* @param {*} val value
* @param {*} onR onReject or onResolve
* @param {*} Re2 reject2 or resolve2
*/
function doOnRe(val, onR, Re2) {
// 把当前promise的回调返回值传给下一个promise
var ret = isFunction(onR) && onR(val) || val
// 如果ret是一个promise对象,那在这个promise得到结果才执行resolve2
if (ret && typeof ret['then'] === 'function') {
ret.then(function (val) {
Re2(value)
})
} else {
Re2(ret)
}
}
/**
* then 的功能
* 1、存储回调函数
*/
if (status === PANDING) {
rejectCallback.push(doOnResolve)
resolveCallback.push(doOnReject)
} else if (status === RESOLVE) {
doOnRe(that.value, onResolve, resolve2)
} else {
doOnRe(that.value, onReject, reject2)
}
})
// 2、支持链式回调
return myPromise2
}
// 实现all方法
// Promise.all 可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。
MyPromise.prototype.all = function(promiseArray) {
if (!Array.isArray(promiseArray)) {
throw new TypeError('You must pass an array to all.');
}
return new MyPromise((resolve, reject) => {
let pNum = promiseArray.length
let successNum = 0
// 用来保存各个promise的回调结果
let result = []
for(let i = 0; i < pNum; i++) {
promiseArray[i].then((res) => {
successNum ++
result.push(res)
// 如果所有都已经成功了
if (successNum === pNum) {
resolve(result)
}
}, (err) => {
reject(err)
break;
})
}
})
}
// 实现race
/**
* const p = Promise.race([p1, p2, p3]);
上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
*/
MyPromise.prototype.race = function(promiseArray) {
if (!Array.isArray(promiseArray)) {
throw new TypeError('You must pass an array to all.');
}
return new MyPromise((resolve, reject) => {
let pNum = promiseArray.length
for(let i = 0; i< pNum; i++) {
promiseArray[i].then(res => {
resolve(res)
break;
})
}
})
}