1.模拟all()方法
在Promise函数中的 all() 方法里面,能够实现在多个Promise对象里面,如果状态全部为resolve的话,则all() 方法返回的结果是resolve,并将所有的Promise对象放到一个数组里面;如果有一个状态为reject的话,则all()方法返回的结果是reject,将第一个出现reject对象的下标作为PromiseResult的值。演示代码如下
<script>
static all(proms) {
return new MyPromise((resolve, reject) => {
const res = proms.map(p => {
const obj = {
result: undefined,
isResolved: false
}
p.then(data => {
obj.result = data;
obj.isResolved = true;
const unResolved = res.filter(r => !r.isResolved)
if (unResolved.length === 0) {
// 全是resolved
resolve(res.map(r => r.result))
}
}, err => {
reject(err)
})
return obj
})
})
}
</script>
2.模拟race() 方法
在Promise函数中的 race() 方法里面,能够实现在多个Promise对象里面,谁的对象状态先推出来,那么PromiseState就显示谁的状态,PromiseResult为最先推出的那个index值,如果是resolve就是resolve,反之则为reject。演示代码如下。
<script>
static race(proms) {
return new MyPromise((resolve, reject) => {
proms.forEach(p => {
p.then(data => {
resolve(data)
}, err => {
reject(err)
})
})
})
}
</script>
总体代码如下:
const MyPromise = (() => {
// 定义三种状态
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
// 不让外界访问,定义符号属性,状态,数据
const PromiseResult = Symbol('PromiseResult');
const PromiseState = Symbol('PromiseState');
// 定义两个任务队列,存储成功后的后续处理和失败后的后续
const thenables = Symbol('thenables');
const catchables = Symbol('catchables');
const changeState = Symbol('changeState');
const settleHandle = Symbol('settleHandle');
const linkPromise = Symbol('linkPromise');
return class Mypromise {
constructor(executor) {
this[PromiseState] = PENDING;
this[PromiseResult] = undefined;
// 定义任务队列数组
this[thenables] = [];
this[catchables] = [];
// 定义成功或失败的推向函数
const resolve = data => {
// 只能单向推状态
// if(this[PromiseState] !== PENDING){
// return ;
// }
// // 只能是未决到已决
// this[PromiseState] = RESOLVED;
// this[PromiseResult] = data
this[changeState](RESOLVED, data, this[thenables])
}
const reject = reason => {
// 只能单向推状态
// if(this[PromiseState] !== PENDING){
// return ;
// }
// // 未决到已决
// this[PromiseState] = RESOLVED;
// this[PromiseResult] = data;
this[changeState](REJECTED, data, this[thenables])
}
// executor(resolve,reject)
// 从未决阶段推向已决阶段不仅可以使用resolve和reject函数,也可以使用抛出错误的方式
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
// 定义改变状态的方法
// newState 新的状态
// newValue 新的数据
// queue 任务队列
[changeState](newState, newValue, queue) {
if (this[PromiseState] !== PENDING) {
return;
}
// 只能是未决到已决
this[PromiseState] = newState;
this[PromiseResult] = newValue;
queue.forEach(handle => handle(newValue));
}
// 定义then方法
then(thenable, catchable) {
// 1.需要将thenable和catchable放入任务队列中等待promise为已决阶段时执行
// if(this[PromiseState] === RESOLVED){
// // 如果是resolved状态则可以执行thenable
// thenable(this[PromiseResult])
// }else{
// this[thenables].push(thenable) // 只是放入并没有执行
// }
// // 直接调用catch处理失败
// this[settleHandle](RESOLVED,thenable,this[thenables])
// this.catch(catchable)
return this[linkPromise](thenable, catchable)
}
catch (catchable) {
// if(this[PromiseState] === REJECTED){
// // 如果是resolved状态则可以直击接执行thenable
// catchable(this[PromiseResult])
// }else{
// this[catchables].push(catchable) // 只是放入还没有执行
// }
// this[settleHandle](REJECTED,catchable.this[catchables])
return this[linkPromise](undefined, catchable)
}
// 提取then和catch的公共代码
// immediateState 立即执行的状态
// handler 后续处理函数
// queue 任务队列
[settleHandle](immediateState, handle, queue) {
if (typeof handle !== 'function') {
return;
}
if (this[PromiseState] === immediateState) {
// 如果是resolved 状态则可以直接执行thenable
// 异步微任务 只能使用宏任务模拟
setTimeout(() => {
handle(this[PromiseResult])
}, 0);
} else {
queue.push(handle) //只是放入还没有执行
}
}
// 定义串联函数
// thenable : fun
[linkPromise](thenable, catchable) {
function exec(data, handle, resolve, reject) {
try {
// 得到一个Promise的处理结果
const result = handle(data)
if (result instanceof MyPromise) {
result.then(d => {
resolve(d)
}, err => {
reject(err)
})
} else {
resolve(result)
}
} catch (error) {
reject(error)
}
}
// 1.该函数执行完后需要返回一个promise对象
// 2.完成基础功能:settleHandle
return new MyPromise((resolve,reject) =>{
this[settleHandle](RESOLVED,data =>{ //qwe
exec(data,thenable,resolve,reject)
},this[thenables])
this[settleHandle](REJECTED,reason =>{
exec(reason,catchable,resolve,reject)
},this[catchables])
})
}
static all(proms) {
return new MyPromise((resolve, reject) => {
const res = proms.map(p => {
const obj = {
result: undefined,
isResolved: false
}
p.then(data => {
obj.result = data;
obj.isResolved = true;
const unResolved = res.filter(r => !r.isResolved)
if (unResolved.length === 0) {
// 全是resolved
resolve(res.map(r => r.result))
}
}, err => {
reject(err)
})
return obj
})
})
}
static race(proms) {
return new MyPromise((resolve, reject) => {
proms.forEach(p => {
p.then(data => {
resolve(data)
}, err => {
reject(err)
})
})
})
}
static resolve(data) {
if (data instanceof MyPromise) {
return data
} else {
return new MyPromise(resolve => {
resolve(data)
})
}
}
static reject(data) {
return new MyPromise((resolve, reject) => {
reject(data)
})
}
}
})()