Promise的理解
/* 对于原生的promise的使用:
promise对象在创建时传入业务的回调函数;
该回调函数需要传递两个参数,resovle与reject用于针对业务的完成情况改变promise状态
promise包含三种状态:pending等待任务完成,fulfilled:任务完成,rejected:任务失败
当一个promise的状态不再是pending状态那么peromise的状态将不再发生改变
promise中的then函数会根据当前promise的执行结果或者状态选择调用回调函数并,返回一个新的promise*/
/* const promise = new Promise((resolve,reject)=>{
console.log(1111);
resolve(1);
})
promise.then((res)=>{
return res;
}).then((res)=>{
console.log(res)
}) */
/* 手撕开始 */
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise{
/* 定义私有成员变量 ,并初始化*/
#states = "pending"
#result = null
#handles = []
/* 创建一个微服务,使得异步执行完毕后尽快执行相关的回调代码 */
nextTick(fn){
// 是node环境
if (process && process.nextTick) {
process.nextTick(fn)
} else {
// 不是node环境,setTimeout适用于其他环境,比如浏览器
setTimeout(fn, 0)
}
}
/* 这里为什么要单独使用run函数执行这些回调函数,首先在执行then方法的时候可能出现的情况是
当前promise的状态还是pending状态,这时候显然不能去执行then的回调函数,我们需要在当前peomise
状态改变那一刻去执行回调函数,这里利用一个handles映射这些回调函数,再在一个单独的函数中去
调用这些函数。这个handles是一个数组是因为用户可能多次去调用then函数*/
#changStates(states,res)
{
if(this.#states === PENDING){
this.#result = res;
this.#states = states;
}
this.#run();
}
#runOne(states,callBack,resolve,reject){
this.nextTick(()=>{
if(this.#states!==states)return;
if(typeof callBack ==="function"){
try{
const data = callBack(this.#result);
resolve(data);
} catch (err) {
reject(err)
}
}else{
if(this.#states ===FULFILLED){
resolve(this.#result)
}else{
reject(this.#result)
}
return
}
})
}
/*哪些情况下使用 resolve, reject:
首先传递的不是函数————穿透
第二中传入执行的回调函数运行时抛出异常,这里reject返回结果
回调函数的返回结果是一个promise*/
#run(){
if(this.#states === PENDING)return;
while(this.#handles.length){
const {fnRes, fnRej, resolve, reject} = this.#handles.shift();
if(this.#states === FULFILLED){
this.#runOne(this.#states,fnRes,resolve,reject);
}else{
this.#runOne(this.#states,fnRej,resolve,reject);
}
}
}
resolve(res){
this.#changStates(FULFILLED,res);
}
reject(err){
this.#changStates(REJECTED,err);
}
then(fnRes,fnRej){
return new Promise((resolve,reject)=>{
this.#handles.push(
{
fnRes,
fnRej,
resolve,
reject
}
)
this.#run();
})
}
/* 在构造函数中定义resolve与reject函数,可以在构造函数外部定义
但是需要注意的是在外部定义,当函数以独立函数形式调用时, this
默认指向全局对象(在浏览器环境下是 window 对象,Node.js 环境下
是 global 对象。)如果我们要将该函数以作为对象的方法调用需要将
this的指向绑定为当前对象的this指向 例如:this.resolve(this),实
际还是定义了一个新的成员方法,这里也可以直接在构造函数中定义*/
constructor(excutor){
excutor(this.resolve.bind(this),this.reject.bind(this));
};
}
const my =new MyPromise((resolve,reject)=>{
setTimeout(()=>{
reject(2);
},1000)
});
const pro = my.then(111,111)
pro.then(111,(res)=>{
console.log(res)
})