写在前面
这人有点懒,就这么懒怎么啦,哈哈,其实不知道怎么写好,但就想尝试与大家分享一下,没兴趣的可以飘过
有兴趣的可以关注我的 gitHub 或者一起研究和探讨。
期待大家来点评
顺便推荐一下我的一个开源库 UnityFront
废话不多说直接上源码。
源码
此版本实现了Promise所有的方法,后续可扩展
说明:内部机制跟官方Promise有些出入,但基本功能以实现,如需使用,请各自调优
export interface PromiseConstructor<T> {
onfulfilled: Array<(value: any) => T>;
onrejected: Array<(value: any) => T>;
onFinally: Array<() => T>;
new<T>(executor: (resolve?: (value?: T) => void, reject?: (reason?: any) => void) => void): PromiseConstructor<T[]>;
then<TResult1 = T, TResult2 = never>(onfulfilled: (value: T) => TResult1, onrejected?: (value: any) => TResult2): PromiseConstructor<T>
catch<TResult2 = never>(onrejected: (value: any) => TResult2): PromiseConstructor<T>
reject<T = never>(reason?: any): PromiseConstructor<T>;
resolve<T>(value: T): PromiseConstructor<T>;
resolve(): PromiseConstructor<T>;
resolve(...args:Array<T>): PromiseConstructor<T>;
finally(onFinally:()=>void): PromiseConstructor<T>;
all<T>(values: Array<PromiseConstructor<T>>): PromiseConstructor<T>;
allSettled<T>(values: Array<PromiseConstructor<T>>): PromiseConstructor<T>;
any<T>(values: Array<PromiseConstructor<T>>): PromiseConstructor<T>;
race<T>(values: Array<PromiseConstructor<T>>): PromiseConstructor<T>;
}
export interface PromiseClass extends PromiseConstructor<any>{}
/**
* Finally 函数处理
* @param allPublicResUlt 当前实例
*/
export const onFinallyPublic = (allPublicResUlt)=>{
setTimeout(()=>{
if(Object.prototype.toString.call(allPublicResUlt.onFinally) === "[object Array]"){
while (allPublicResUlt.onFinally.length > 0){
allPublicResUlt.onFinally.shift()();
}
}
})
}
/**
* 全部批处理公共函数
* @param value 待批处理的 PromiseClass 数组
* @param type 执行类型:all | allSettled
*/
export const allPublic = function (value: Array<any>, type:string = "all"):PromiseConstructor<any>{
if(Object.prototype.toString.call(value) !== "[object Array]"){
throw ("不是一个有效的数组");
}
let lng = value.length;
// 创建长度与value长度一致的数据,并默认填充[object Empty]类型,用于等待查询判断
let resUlt_resolve = (<any>"_").repeat(lng).split("").map(()=>"[object Empty]");
let resUlt_reject = null;
let resUlt_reject_bool = false;
const getRes = (res:any, resType:number)=>({
"all":res,
"any":res,
"race":res,
"allSettled":{
status:[1,3].some(t=>t === resType) ? "fulfilled" : "rejected",
value:res,
}
}[type] || res);
value.forEach((it:any,k)=>{
if (it && it.constructor && it.constructor.name === "PromiseClass") {
it.then(res=>{
resUlt_resolve[k] = getRes(res,1);
}).catch(res=>{
if(type === "allSettled"){
resUlt_resolve[k] = getRes(res,2);
return;
}
if(!resUlt_reject_bool){
resUlt_reject = getRes(res,2);
resUlt_reject_bool = true;
}
})
}else {
resUlt_resolve[k] = getRes(it,3);
}
});
const allPublicResUlt = new PromiseClass((resolve1, reject1) => {
const InquireFun = ()=>{
new PromiseClass((resolve2, reject2) => {
if(resUlt_resolve.filter(e=>e !== "[object Empty]").length === lng){
// 全部成功
resolve2(resUlt_resolve);
}else {
if(resUlt_reject_bool){
// 任何一个失败
reject2(resUlt_reject);
}else {
// 即没失败也没成功,则继续等待询问
InquireFun()
}
}
}).then((res)=>{
let rarr = resUlt_resolve.filter(e=>e !== "[object Empty]");
if(type === "any"){
if (rarr.length > 0){
resolve1(rarr[0])
}else {
reject1("全部执行完成,但没有成功的")
}
return;
}
if(type === "race"){
if(resUlt_reject_bool){
resolve1(resUlt_reject);
}else {
reject1("全部执行完成,但没有失败的")
}
return;
}
resolve1(res)
}).catch((err)=>{
let rarr = resUlt_resolve.filter(e=>e !== "[object Empty]");
if(type === "any"){
if (rarr.length > 0){
resolve1(rarr[0])
}else {
reject1("全部执行完成,但没有成功的")
}
return;
}
if(type === "race"){
if(resUlt_reject_bool){
resolve1(resUlt_reject);
}else {
reject1("全部执行完成,但没有失败的")
}
return;
}
reject1(err)
})
}
InquireFun();
}).then(res=>{
onFinallyPublic(allPublicResUlt);
return res;
}).catch(res=>{
onFinallyPublic(allPublicResUlt);
return res;
})
return allPublicResUlt;
}
/**
* 递归执行 成功或失败回调
* @param onfulfilled 成功回调数组
* @param onrejected 失败回调数组
* @param arg 参数
* @param bool 是否失败
*/
export const resultResolve = function (onfulfilled:Array<(value: any) => any>, onrejected:Array<(value: any) => any>, arg:Array<any>, bool:boolean = true) {
if (onfulfilled) {
if(typeof onfulfilled[0] === "function"){
let value = onfulfilled.shift().apply(null, arg);
if (value && value.constructor && value.constructor.name === "PromiseClass") {
value
.then(res => {
if(bool){
resultResolve.call(this,onfulfilled, onrejected, [res], bool);
}else {
resultResolve.call(this,onrejected,onfulfilled, [res] , false);
}
})
.catch(res=>{
resultResolve.call(this,onrejected,onfulfilled, [res] , false);
})
} else {
resultResolve.call(this,onfulfilled, onrejected, [value], bool);
}
}
}
}
export class PromiseClass<T = any> implements PromiseClass<T> {
onfulfilled = [];
onrejected = [];
onFinally = [];
constructor(executor: (resolve?: (value?: T) => void, reject?: (reason?: any) => void) => void) {
setTimeout(() => {
executor(this.resolve.bind(this), this.reject.bind(this));
});
}
then<TResult1 = T, TResult2 = never>(onfulfilled?: (value: T) => TResult1, onrejected?: (value: any) => TResult2): PromiseClass<T> {
if (onfulfilled) {
this.onfulfilled.push(<any>onfulfilled)
}
if (onrejected) {
this.onrejected.push(<any>onrejected)
}
return this;
}
catch<TResult2 = never>(onrejected?: (value: any) => TResult2): PromiseClass<T> {
if (onrejected) {
this.onrejected.push(onrejected)
}
return this;
}
finally(onFinally:()=>void): PromiseClass<T> {
if (onFinally) {
this.onFinally.push(onFinally)
}
return this;
}
resolve(...args: Array<any>): PromiseConstructor<any> | any {
resultResolve.call(this,this.onfulfilled,this.onrejected, args, true);
onFinallyPublic(this);
}
reject(...arg): PromiseConstructor<any> | any {
resultResolve.call(this,this.onrejected,this.onfulfilled, arg, false);
onFinallyPublic(this);
}
static resolve(...args): PromiseConstructor<any> {
this.prototype.resolve.apply(this, args)
return new PromiseClass((resolve) => {
resolve.apply(null, args);
});;
}
static reject(...args): PromiseConstructor<any> {
this.prototype.reject.apply(this, args)
return new PromiseClass((resolve, reject) => {
reject.apply(null, args);
});
}
static all(value: Array<any>):PromiseConstructor<any>{
return allPublic(value, "all");
}
static allSettled(value: Array<any>):PromiseConstructor<any>{
return allPublic(value, "allSettled");
}
static any(value: Array<any>):PromiseConstructor<any>{
return allPublic(value, "any");
}
static race(value: Array<any>):PromiseConstructor<any>{
return allPublic(value, "race");
}
}
export default PromiseClass;