Promise实现过程
构造函数
class A{
constructor(exec){}
}
let a1 = new A((resolve,reject)=>{
});
定义resolve,reject
-
这两个函数用于改变当前对象的状态以及存放数据
-
只有当调用resolve/reject时, 才能确定对象的状态及数据,否则对象都是pending状态
- 第一步先把 resolve, reject 如何正确的传进去
// resolve,reject函数名可随意更改
class A{
constructor(exec){
/*
这样做对吗?
这两个函数在匿名函数中直接使用,
需要bind this, 不然拿不到this
*/
//exec(this.resolve,this.reject);
//修改如下
exec(this.resolve.bind(this),this.reject.bind(this));
}
resolve( value ) {}
reject( reason ){}
}
let a1 = new A((resolve,reject)=>{
resolve(111); //这里直接调用
});
添加几个常量用于对象的状态以及初始值
//定义3个状态
const Promise_State = {
pending:0, fulfilled:1,rejected:2
};
//定义3个字符串,不用也行
Promise_State_String = {
0:'pending',1:'fulfilled',2:'rejected'
};
class A{
//状态
state = Promise_State.pending;
//状态字符串
state_str = Promise_State_String[Promise_State.pending];
//数据
result = undefined;
constructor(exec){
//检查是否是一个函数
if(exec instanceof Function)
exec(this.resolve.bind(this),this.reject.bind(this));
}
resolve(value){}
reject(reason){}
}
resolve的函数处理
- 对象的状态只在resolve以及reject中设置,数据也是如此
- 且只能设置一次(调用一次)
class A{
//省略其他
//设置状态,数据
resolve(value){
//根据状态判断
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.fulfilled;
this.state_str = Promise_State_String[this.state];
this.result = value;
}
reject(reason){
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.rejected;
this.state_str = Promise_State_String[this.state];
this.result = reason;
}
}
then 用来注册回调函数
- then 需要处理2种情况, 同步回调/异步回调
- 无论哪种情况,都是根据当前对象状态来执行对应的回调函数
-
- fulfilled状态执行第一个回调
-
- rejected执行第二个回调
-
注意: 同步情况都是在 resolve() / reject() 已经调用完成后才是同步
- 同步状态下, 当前对象的状态一定是fulfilled / rejcted
- 先处理同步情况
class A{
//其他省略
then(success, failed){
//fulfilled状态
if(Promise_State.fulfilled === this.state){
success(this.result);
}
//rejcted状态
else if(Promise_State.rejected === this.state){
failed(this.result);
}
}
}
let a1 = new A((resolve,reject)=>{
reject(111);
});
a1.then(null, res=>{
console.log(res); // 1111
});
then中的异步调用
- 在异步调用中,所有在then注册的回调函数将在resolve/reject中执行
-
- 异步情况, 对象状态:pending
-
- 同步情况, 对象状态已经由pending转成fulfilled/rejected
-
- 由于同一个对象可多次调用then,因此需要使用数组保存回调函数
-
-
注:异步情况下,只有当对象的resolve/reject调用时才会调用所有在then中注册的回调函数
//伪代码
success_callbacks = [] // 保存第一个回调函数
failed_callbacks = [] // 保存第二个回调函数
resolve(){
...
success_callbacks.foreach(callback=>{
callback();
})
}
then(success,failed){
if(是异步状态){
/*
注册回调函数
往数组放一个匿名函数,方便传入this.result
*/
success_callbacks.push(()=>{
success(this.result);
} );
failed_callbacks.push( ()=>{
failed(this.result);
} );
}
else{
同步状态 ...
}
}
//定义3个状态
const Promise_State = {
pending:0, fulfilled:1,rejected:2
};
//定义3个字符串,不用也行
const Promise_State_String = {
0:'pending',1:'fulfilled',2:'rejected'
};
class A{
//状态
state = Promise_State.pending;
//状态字符串
state_str = Promise_State_String[Promise_State.pending];
//数据
result = undefined;
//回调数组
success_callbacks = [];
failed_callbacks = [];
constructor(exec){
if(exec instanceof Function)
exec(this.resolve.bind(this),this.reject.bind(this));
}
//设置状态,数据
resolve(value){
//根据状态判断
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.fulfilled;
this.state_str = Promise_State_String[this.state];
this.result = value;
// 调用所有成功回调
this.success_callbacks.forEach(cb=>{
cb();
});
}
reject(reason){
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.rejected;
this.state_str = Promise_State_String[this.state];
this.result = reason;
//调用所有失败回调
this.failed_callbacks.forEach(cb=>{
cb();
});
}
then(success, failed){
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
success(this.result);
});
this.failed_callbacks.push(()=>{
failed(this.result);
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
success(this.result);
}
//rejcted状态
else if(Promise_State.rejected === this.state){
failed(this.result);
}
}
}
}
let a1 = new A((resolve,reject)=>{
setTimeout(() => {
reject(111);
}, 0);
});
//未调用reject: state: 0, state_str: 'pending', result: undefined
console.log('未调用reject:',a1);
a1.then(null, res=>{
console.log(res); // 1111
});
//调用reject后: A state: 2, state_str: 'rejected', result: 111,
setTimeout(() => {
console.log('调用reject后:',a1);
}, 100);
then 返回新对象(new Promise)
- then返回一个新Promise
- 新Promise的状态及数据:
-
- 新Promise将等待当前Promise调用回调后才会执行自己的resolve/reject
-
- 新Promise将获取当前Promise回调函数的返回值,作为自己的数据
-
- 注:新Promise的resolve/reject的被调用时机是在当前Promise的resolve/reject中的回调函数中
//伪代码
then(){
//创建一个新对象
let o = new A();
// 异步状态
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//此匿名函数将在当前Promise的resolve中调用
//获取返回值
let res = success(this.result);
//把结果传递给新对象
o.resolve(res);
});
}
else {
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
let res = success(this.result);
//获取返回值立即调用
o.resolve(res);
}
}
}
then(success, failed){
let obj = new A();
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//在当前Promise的resolve中调用
let res = success(this.result);
obj.resolve(res);
});
this.failed_callbacks.push(()=>{
//在当前Promise的reject中调用
obj.reject(failed(this.result));
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
obj.resolve(success(this.result));
}
//rejcted状态
else if(Promise_State.rejected === this.state){
obj.reject(failed(this.result));
}
}
return obj;
}
then的回调如果为空及异常处理
- 上面的代码其实一直有个大问题
-
- then中没有对传入的回调做为空判断
-
- 上面的代码中新对象的状态是根据当前对象状态来改变的,这是有问题的,如果有对应回调,那么新对象的状态应该是fulfilled
-
- 在原生Promise的then中如果有对应回调,fulfilled=>有对应回调/ rejected=>有对应回调,那么返回的新Promise状态为fulfilled
-
- 如果没有对应回调,则应该复制自己的状态及数据给新Promise
//原生Promise例子:
let o1 = Promise.reject(1); //rejected状态
let o2 = o1.then(null, res=>{ //有对应回调
return 123;
});
setTimeout(() => {
//[[PromiseState]]: 'fulfilled', [[PromiseResult]]: 123
console.log(o2);
}, 10);
1.修改then中所有新Promise的调用
- 增加回调函数中的异常处理
- 如果在回调函数中发生异常,那么新对象的状态应该为rejected
- 把所有新对象的调用换为resolve
//目前无法处理回调中发生异常的情况
//例子:
let a2 = a1.then(null, res=>{
//目前无法处理异常问题
throw new Error('123');
});
then(success, failed){
let obj = new A();
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//在当前Promise的resolve中调用
try {
obj.resolve(success(this.result));
} catch (error) {
obj.reject(error);
}
});
this.failed_callbacks.push(()=>{
//在当前Promise的reject中调用
try {
obj.resolve(failed(this.result));
} catch (error) {
obj.reject(error);
}
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
try {
obj.resolve(success(this.result));
} catch (error) {
obj.reject(error);
}
}
//rejcted状态
else if(Promise_State.rejected === this.state){
try {
obj.resolve(failed(this.result));
} catch (error) {
obj.reject(error);
}
}
}
return obj;
}
2.then中传入的回调如果为空时的状态及数据传递
- 在原生Promise中,如果then没有对应回调
-
- 将传递自身的状态及数据给新Promise,让新Promise去处理
- 对传入回调做判断,并给与默认函数
- 这两个默认函数需要有传递自身数据的能力
then(success, failed){
/*
加入判断, 给与默认函数
对于fulfilled状态如果没有对应函数,直接返回传入的数据
这样新Promise就能获得返回值并调用自己的resolve()
对于rejected状态如果没有对应函数, 抛出当前对象的this.result
这样新Promise在catch中捕获this.result,同时调用reject()
如此,就相当于把状态及数据传递给了新Promise
*/
if( 'function' !== typeof success )
success = res=>res;
if( 'function' !== typeof failed )
failed = res=>{ throw res };
//其他代码不变
}
3.then中的冗余代码改造(可省略)
//伪代码
/*
then中的重复代码
结构一致
*/
try {
obj.resolve(success(this.result));
} catch (error) {
obj.reject(error);
}
//增加一个函数, 公用代码
common_func_in_then(new_promise_resolve,
new_promise_reject,
callback ,
result){
try {
let res = callback(result);
new_promise_resolve(res);
} catch (error) {
new_promise_reject(error);
}
/*
如此则需要在then中额外做一些处理
*/
// 用于公用代码,需要绑定 obj
let new_promise_resolve = obj.resolve.bind(obj);
let new_promise_reject = obj.reject.bind(obj);
/*
不能直接传递 obj.resolve, obj.reject
传递进去可以被调用,但 this 找不到了
所以必须bind
*/
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
failed,
this.result
);
}
//then中使用的公共代码
common_func_in_then(new_promise_resolve,new_promise_reject, callback , result){
try {
let res = callback(result);
new_promise_resolve(res);
} catch (error) {
new_promise_reject(error);
}
}
then(success, failed){
if( 'function' !== typeof success )
success = res=>res;
if( 'function' !== typeof failed )
failed = res=>{ throw res };
let obj = new A();
//用于公用代码,需要绑定 obj
let new_promise_resolve = obj.resolve.bind(obj);
let new_promise_reject = obj.reject.bind(obj);
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//在当前Promise的resolve中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
success,
this.result
);
});
this.failed_callbacks.push(()=>{
//在当前Promise的reject中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
failed,
this.result
);
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
this.common_func_in_then(new_promise_resolve,
new_promise_reject,success,this.result
);
}
//rejcted状态
else if(Promise_State.rejected === this.state){
this.common_func_in_then(new_promise_resolve,
new_promise_reject,failed,this.result
);
}
}
return obj;
}
then的回调函数中如果返回的是一个Promise
- 如果回调中返回的是一个Promise
- 那么创建的新Promise则需要等待返回的Promise执行完成
//伪代码
let a1 = new A((resolve,reject)=>{
reject(111);
});
let a2 = a1.then(null, res=>{
//目前无法处理这种情况
return new A((r,j)=>{
j(123);
});
});
// 目前获取回调返回值的地方在common_func_in_then中
common_func_in_then(
new_promise_resolve,
new_promise_reject,
callback ,
result){
try {
//如果 res 是一个Promise 则需要额外处理
let res = callback(result);
if(如果 res 是一个Promise){
/*
为 res 添加2个回调函数(then的可连续调用)
res 需要花多长时间,总会调用到这两个函数的其中一个
新对象一直等到 res 调用新添加的回调为止
*/
res.then(x=>{
// 如果成功
new_promise_resolve(x);
},x=>{
// 如果失败
new_promise_reject(x);
});
}
else{
//正常处理
new_promise_resolve(res);
}
} catch (error) {
new_promise_reject(error);
}
}
common_func_in_then(
new_promise_resolve,
new_promise_reject,
callback ,
result) {
try {
let res = callback(result);
//如果是一个Promise
if(res instanceof A){
res.then(res=>{
new_promise_resolve(res);
},res=>{
new_promise_reject(res);
});
}
else
new_promise_resolve(res);
} catch (error) {
new_promise_reject(error);
}
}
关于一些代码上的优化 使用queueMicrotask (可省略)
- 这部分根据个人需求改造
- 使用queueMicrotask只是为了让主线程快点响应
- 可以在then的同步处理和resolve/reject中的回调中使用
- 注意只在直接调用回调函数的地方使用,调用回调函数需要时间因此使用,主要为了让主线程快点响应
//具体用法
queueMicrotask( ()=>{
//把原本的代码移入到这
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
success,
this.result
);
} );
resolve(value){
//其他不变
queueMicrotask(()=>{
this.success_callbacks.forEach(cb=>{
cb();
});
})
}
reject(reason){
//其他不变
queueMicrotask(()=>{
this.failed_callbacks.forEach(cb=>{
cb();
});
});
}
then(){
//其他不变
//同步代码块中
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,success,this.result
);
});
}
//rejcted状态
else if(Promise_State.rejected === this.state){
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,failed,this.result
);
});
}
}
}
至此Promise完成
//定义3个状态
const Promise_State = {
pending:0, fulfilled:1,rejected:2
};
//定义3个字符串,不用也行
const Promise_State_String = {
0:'pending',1:'fulfilled',2:'rejected'
};
class A{
//状态
state = Promise_State.pending;
//状态字符串
state_str = Promise_State_String[Promise_State.pending];
//数据
result = undefined;
//回调数组
success_callbacks = [];
failed_callbacks = [];
constructor(exec){
if(exec instanceof Function)
exec(this.resolve.bind(this),this.reject.bind(this));
}
//设置状态,数据
resolve(value){
//根据状态判断
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.fulfilled;
this.state_str = Promise_State_String[this.state];
this.result = value;
queueMicrotask(()=>{
this.success_callbacks.forEach(cb=>{
cb();
});
})
}
reject(reason){
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.rejected;
this.state_str = Promise_State_String[this.state];
this.result = reason;
queueMicrotask(()=>{
this.failed_callbacks.forEach(cb=>{
cb();
});
});
}
common_func_in_then(new_promise_resolve,new_promise_reject, callback , result){
try {
let res = callback(result);
if(res instanceof A){
res.then(res=>{
new_promise_resolve(res);
},res=>{
new_promise_reject(res);
});
}
else
new_promise_resolve(res);
} catch (error) {
new_promise_reject(error);
}
}
then(success, failed){
if( 'function' !== typeof success )
success = res=>res;
if( 'function' !== typeof failed )
failed = res=>{ throw res };
let obj = new A();
//用于公用代码,需要绑定 obj
let new_promise_resolve = obj.resolve.bind(obj);
let new_promise_reject = obj.reject.bind(obj);
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//在当前Promise的resolve中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
success,
this.result
);
});
this.failed_callbacks.push(()=>{
//在当前Promise的reject中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
failed,
this.result
);
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,success,this.result
);
});
}
//rejcted状态
else if(Promise_State.rejected === this.state){
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,failed,this.result
);
});
}
}
return obj;
}
}
其他函数的实现
- catch, finally, resolve,reject,allSettled, all, race, any的实现
- 完整代码
//定义3个状态
const Promise_State = {
pending:0, fulfilled:1,rejected:2
};
//定义3个字符串,不用也行
const Promise_State_String = {
0:'pending',1:'fulfilled',2:'rejected'
};
//错误常量
const Promise_Error = {
arg_not_array:'参数不是数组'
}
class A{
//状态
state = Promise_State.pending;
//状态字符串
state_str = Promise_State_String[Promise_State.pending];
//数据
result = undefined;
//回调数组
success_callbacks = [];
failed_callbacks = [];
constructor(exec){
if(exec instanceof Function)
exec(this.resolve.bind(this),this.reject.bind(this));
}
//设置状态,数据
resolve(value){
//根据状态判断
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.fulfilled;
this.state_str = Promise_State_String[this.state];
this.result = value;
queueMicrotask(()=>{
this.success_callbacks.forEach(cb=>{
cb();
});
})
}
reject(reason){
if(Promise_State.pending !== this.state)
return;
this.state = Promise_State.rejected;
this.state_str = Promise_State_String[this.state];
this.result = reason;
queueMicrotask(()=>{
this.failed_callbacks.forEach(cb=>{
cb();
});
});
}
common_func_in_then(new_promise_resolve,new_promise_reject, callback , result){
try {
let res = callback(result);
if(res instanceof A){
res.then(res=>{
new_promise_resolve(res);
},res=>{
new_promise_reject(res);
});
}
else
new_promise_resolve(res);
} catch (error) {
new_promise_reject(error);
}
}
then(success, failed){
if( 'function' !== typeof success )
success = res=>res;
if( 'function' !== typeof failed )
failed = res=>{ throw res };
let obj = new A();
//用于公用代码,需要绑定 obj
let new_promise_resolve = obj.resolve.bind(obj);
let new_promise_reject = obj.reject.bind(obj);
//异步情况
if(Promise_State.pending === this.state){
this.success_callbacks.push(()=>{
//在当前Promise的resolve中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
success,
this.result
);
});
this.failed_callbacks.push(()=>{
//在当前Promise的reject中调用
this.common_func_in_then(
new_promise_resolve,
new_promise_reject,
failed,
this.result
);
});
}
else{
//同步情况
//fulfilled状态
if(Promise_State.fulfilled === this.state){
//立即调用
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,success,this.result
);
});
}
//rejcted状态
else if(Promise_State.rejected === this.state){
queueMicrotask(()=>{
this.common_func_in_then(new_promise_resolve,
new_promise_reject,failed,this.result
);
});
}
}
return obj;
}
//语法糖
catch(failed){
return this.then(undefined, failed);
}
//不论什么情况都能调用
finally(cb){
return this.then(cb,cb);
}
// 语法糖
static resolve(value){
if(value instanceof A)
return value;
return new A(( r , j ) =>{
r(value);
});
}
// 语法糖
static reject(value){
return new A((r , j) =>{
return j(value);
});
}
//包装函数
static pack(value){
if(value instanceof A)
return value;
return new A((r , j)=>{
r(value);
});
}
// 看哪个 Promise 快,即使出错
static race(arr){
if(!Array.isArray(arr))
throw new Error(Promise_Error.arg_not_array);
return new A((r , j ) =>{
arr.forEach(obj=>{
//obj 不一定是 promise 因此包装
//确保每个obj都是 Promise
let promise = A.pack(obj);
//给每一个promise添加回调
promise.then(res=>{
r(res);
},res=>{
j(res);
});
});
});
}
//用于展示
to_object(){
return {
'state':this.state,
'state_str':this.state_str,
'result':this.result
};
}
//看哪个Promise快, 如果有错误那么等待所有错误
static any(arr){
if(!Array.isArray(arr))
throw new Error(Promise_Error.arg_not_array);
if(0 === arr.length)
return A.reject(arr);
return new A((r , j) => {
let arr_len = arr.length;
let count = 0;
let result = [];
arr.forEach((obj, index)=>{
let promise = A.pack(obj);
promise.then(res=>{
r(res);
},res=>{
result[index] = promise.to_object();
count++;
// 所有Promise全部失败
if(arr_len === count)
j(res);
});
});
});
}
//等待所有Promise完成, 除非有错
static all(arr){
if(!Array.isArray(arr))
throw new Error(Promise_Error.arg_not_array);
if(0 === arr.length )
return A.resolve(arr);
return new A((r , j ) =>{
let arr_len = arr.length;
let count = 0 ;
let result = [];
arr.forEach((obj,index)=>{
let promise = A.pack(obj);
promise.then(res=>{
result[index] = res;
count++;
if(arr_len === count)
r(result);
},res=>{
j(res);
});
});
});
}
//等待所有Promise,无论成功还是失败
static allSettled(arr){
if(!Array.isArray(arr))
throw new Error(Promise_Error.arg_not_array);
if(0 === arr.length )
return A.resolve(arr);
return new A(( r , j ) =>{
let arr_len = arr.length;
let count = 0;
let result = [];
arr.forEach((obj,index)=>{
let promise = A.pack(obj);
promise.then(res=>{
result[index] = promise.to_object();
++count;
if(arr_len === count)
r(result);
},res=>{
result[index] = promise.to_object();
++count;
if(arr_len === count)
j(result);
});
});
});
}
}