快速理解Promise

作者: sitorhy | 来源:发表于2018-08-09 17:58 被阅读10次

    一、事件分发机制


    事件分发机制是观察者模式的一种实现,常见于UI交互,给界面组件注册监听器,由界面组件发出事件,监听器接收到事件后作出响应。

    事件分发机制也适用于异步管理,其实UI的事件分发也是一种异步通讯,理解Promise实现之前应该对事件分发器(Event Dispatcher)的实现有所了解,DOM对象也可看作是一种分发器,addEventListenerPromise.then类似,都是监听器注册的入口。

    二、分发器雏形


    实现一个简单的事件分发器Dispatcher,用于封装异步任务task,分发器构造函数须接收一个任务函数task(),对外暴露两个接口,注册监听器register()和执行任务execute(),私有方法trigger()用于触发事件。
    因为任务只执行一次,因此监听器触发一次后便移除。

    接口 参数 说明
    register success,error 任务执行成功回调success(),异常回调error()
    trigger type,data type事件类型,data附加参数如含异常信息等
    execute 执行任务函数task()
    function Dispatcher(task)
    {
        if(typeof task !=="function")
        {
            throw Error("task is not a function.");
        }
    
        this.task=task;
        this.listeners=[];
    };
    
    Dispatcher.prototype.register=function(on_success=()=>{},on_error=()=>{}){
        this.listeners.push({
            on_success,
            on_error
        });
    };
    
    Dispatcher.prototype.trigger=function(type,data)
    {
        switch(type)
        {
            case "success":
            {
                this.listeners.forEach((listener)=>
                {
                    listener.on_success(data);
                });
            }
                break;
            case "error":
            {
                this.listeners.forEach((listener)=>
                {
                    listener.on_error(data);
                });
            }
                break;
        }
    };
    
    Dispatcher.prototype.execute=function(){
        const trigger_success=(data)=>
        {
            this.trigger("success",data);
        };
    
        const trigger_error=(data)=>
        {
            this.trigger("error",data);
        };
    
        this.task(trigger_success,trigger_error);
    };
    

    task()被执行时传入了两个函数trigger_success()trigger_error(),都是对trigger()接口的封装,用于任务结束时反馈执行状态是成功success还是异常error

    例2-1 分发器的基础应用:

    let task=new Dispatcher((trigger_success,trigger_error)=>
    {
        trigger_success();
    });
    
    task.register(()=>
    {
        console.log("task executed.");
    });
    
    task.execute(); // 启动事件源
    

    输出:

    task executed.

    三、挖坑,实现响应延迟注册


    例3-1:

    let task=new Dispatcher((trigger_success,trigger_error)=>
    {
        trigger_success();
    });
    
    task.register(()=>
    {
        console.log("task executed.");
    });
    
    task.execute(); // 启动事件源
    
    setTimeout(()=>
    {
        // 任务结束后注册监听器
        task.register(()=>
        {
            console.log("after 3s."); // 不会被响应
        });
    },3000);
    

    输出:

    task executed.

    如上例子,观察者模式实现的典型是先注册后执行,对于要等到任务结束后才注册监听器的场景遇到的不多,这里挖个坑去实现它。

    首先明确,任务的执行结果是不变的(must not transition to any other state),用Promise/A+的话就是说,任务状态分三种,任务状态初始状态是"pending",完成态是"fulfilled",拒绝态是"rejected",状态仅能由初始态转为完成态或拒绝态。

    这里定义分发器任务的三个状态为初始态"pending",成功态"success"和异常态"error"
    记得注册接口声明为register(on_success,on_error),接口的两个传入函数分别对应成功态和异常态的响应,由分发器负责回调。

    任务是否执行成功,由task()实现逻辑确定,执行成功,回调一下trigger_success()进行反馈,分发器自动触发各个监听器。任务结束后注册的监听器,由于脱离了运作流程是不可能得到响应的,“响应延迟注册”换种说法应该是询问,即询问执行结果,只不过询问的接口依然是register(),两种职责集中在一个接口,是不是有违反单一职责原则的嫌疑呢。

    事实上,register()接口会发生职责转换,从注册监听器用途转为结果查询用途,任务函数task()尚未执行,此时register()为注册监听器用途,一切按流程走;trigger_success/trigger_error被回调后,预注册的监听器得到反馈,之后register()就转为查询用途。
    注册功能原有运作机制已经具有,添加查询用途需要稍作改动,设立标记变量state用于状态的维护和获取,初始化为pending,还有就是缓存任务执行结果(Result)。

    function Dispatcher(task)
    {
        if(typeof task !=="function")
        {
            throw Error("task is not a function.");
        }
    
        this.state="pending"; // 维护状态
        this.result=undefined; // 缓存task执行结果
    
        this.task=task;
        this.listeners=[];
    };
    

    任务函数task()回调trigger_success()trigger_error()事实上就是进行状态转换。

    Dispatcher.prototype.trigger=function(type,data){
        this.state=type; // 修改状态
        this.result=data; //缓存结果
    
        switch(type)
        {
            case "success":
            {
                this.listeners.forEach((listener)=>
                {
                    listener.on_success(data);
                });
            }
                break;
            case "error":
            {
                this.listeners.forEach((listener)=>
                {
                    listener.on_error(data);
                });
            }
                break;
        }
    };
    

    当状态不为pending时,可以认为任务已经执行结束,register()接口职责转为结果查询,根据状态反馈结果即可,监听器不需要缓存进listeners[]

    Dispatcher.prototype.register=function(on_success=()=>{},on_error=()=>{}){
        switch(this.state)
        {
            case "pending":
            {
                this.listeners.push({
                    on_success,
                    on_error
                });
            }
                break;
            case "success":
            {
                on_success(this.result);
            }
                break;
            case "error":
            {
                on_error(this.result);
            }
                break;
        }
    };
    

    改动后再执行例3-1
    输出:

    task executed.
    after 3s.

    四、再挖坑,实现链式调用


    链式调用最早出现于jQuery:

    $(this).children("a").siblings().removeClass("active").addClass("active");
    

    jQuery链式调用返回this,由于操作对象都是自身,操作结果最终会被复合在一起。但对于事件分发器来说,任务逻辑基本是独立的,链式调用的下一个对象应该是一个新的分发器对象,返回分发器自身会造成自身状态反复改写,违反状态转换原则。
    打个草稿,让register()返回一个新的分发器对象,实现任务串联,大概就是如下样子:

    let task1=new Dispatcher((trigger_success,trigger_error)=>
    {
        trigger_success(); // 确认初始状态,启动链式操作
    });
    
    task1.register(()=>
    {
        ... // task1 handler
    }).register(()=>
    {
        ... // task2 handler
    }).register(()=>
    {
        ... // task3 handler
    });
    

    注意,触发链式操作首先要对链头任务进行反馈。

    当监听器回调函数on_success()on_error()有返回值,并且返回值形似一个分发器对象(thenable),register()就接受该对象作为返回值。如果监听器没有返回值,那么register()就返回一个默认实现的分发器,并且该分发器的状态继承本分发器的状态(adopt its state)。

    register()职责是注册监听器时,由于监听器尚未作出响应自然就无法取得on_success()/on_error()的返回值,此时接口返回的是默认值,后续被注册的观察对象也是该默认值。on_success()/on_error()要被延迟到接口trigger()被启动时回调,由于trigger()接口自身没有定义返回值,回调返回的自定义分发器根本没有机会对外暴露接口,为了将返回的默认值与on_success()/on_error()的自定义分发器内容关联起来,应该将默认的返回值与监听器关联起来一并缓存(deferred),待监听器响应前,将自定义分发器的上下文替换掉被缓存默认值分发器的上下文。

    register()职责是查询时,如果监听器返回值具有分发器特征,那么就认为该返回值是一个Dispatcher对象,直接启动即可。

    当任务执行异常时,若register()注册的监听器没有实现异常处理on_error(),则将本级的异常状态和数据往下一级分发器传递,直到被接收为止。异常被接收后,为了使执行链能继续执行,若下一级分发器没有自定义实现,则修改下一级分发器状态为"success"继续执行,直到执行链执行完毕。

    // 默认的监听器回调实现,用于确保register有返回值,on_success/on_error没有显式被实现可以变相理解为采用了默认实现
    // 回调函数返回一个默认实现的分发器,分发器的任务实现就是继承状态和结果(adopt its state),是状态传递的基础
    Dispatcher.prototype.on_success=function(data){
        return new Dispatcher(function(trigger_success,trigger_error){
            trigger_success(data); //继承状态 ‘success’和结果result,两者应当同时继承
        });
    };
    
    // 见上,默认的on_error实现
    Dispatcher.prototype.on_error=function(data){
        return new Dispatcher(function(trigger_success,trigger_error){
            trigger_error(data);
        });
    };
    
    // 回调函数给与了默认指定,确保注册的同时返回新的分发器
    // 自定义任务内容在需要在回调中实现并返回
    Dispatcher.prototype.register=function(on_success=Dispatcher.prototype.on_success,on_error=Dispatcher.prototype.on_error){
        let next; // 下一个分发器
    
        const noop=(trigger_success,trigger_error)=> // 默认的空任务实现
        {
            switch(this.state) // 本级状态,注意指针,该函数修改下一个分发器的状态
            {
                case "success":
                {
                    if(on_success===Dispatcher.prototype.on_success) // 是否实现了回调
                    {
                        trigger_success(this.result); // 继承上一级状态数据,下一级state修改为success
                    }
                    else
                    {
                        trigger_success(); // 已实现,回调下一级on_success
                    }
                }
                    break;
                case "error":
                {
                    if(on_error===Dispatcher.prototype.on_error) // 是否实现了回调
                    {
                        trigger_error(this.result); // 没有实现就继续路由
                    }
                    else
                    {
                        trigger_success(); // 已实现,可认为异常已处理,回调下一级on_success
                    }
                }
            }
        };
    
        switch(this.state)
        {
            case "pending":
            {
                next=new Dispatcher(noop); // 默认分发器
    
                this.listeners.push({
                    on_success,
                    on_error,
                    dispatcher:next // 缓存默认值
                });
            }
                break;
            case "success":
            {
                if(typeof on_success==="function")
                {
                    next=on_success(this.result); // 产生下一级分发器
                    if(!next|| typeof next.register!=="function") // 返回结果是否具有分发器特征
                    {
                        next=new Dispatcher(noop);
                    }
                    next.execute();
                }
            }
                break;
            case "error":
            {
                if(typeof on_error==="function")
                {
                    next=on_error(this.result);
                    if(!next|| typeof next.register!=="function") // 同上,检查是否有自定义任务的分发器
                    {
                        next=new Dispatcher(noop);
                    }
                    next.execute();
                }
            }
                break;
        }
    
        return next;
    };
    
    Dispatcher.prototype.trigger=function(type,data){
        function switchContext(cache,next)
        {
            // 返回值是否具有分发器特征
            if(typeof next.register==="function")
            {
                cache.task=next.task; // 替换上下文
    
                next.task=null;
            }
        }
    
        this.state=type;
        this.result=data;
    
        switch(type)
        {
            case "success":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_success==="function")
                    {
                        let implement=listener.on_success(data); // 接受自定义实现
                        let deferred=listener.dispatcher;
    
                        if(implement&& typeof implement.register==="function")
                        {
                            switchContext(deferred,implement); // 替换上下文
                        }
                        deferred.execute(); // 默认执行noop
                    }
                });
            }
                break;
            case "error":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_error==="function")
                    {
                        let implement=listener.on_error(data);
                        let deferred=listener.dispatcher;
    
                        if(implement&& typeof implement.register==="function")
                        {
                            switchContext(deferred,implement);
                        }
                        deferred.execute(); // 默认执行noop
                    }
                });
            }
                break;
        }
    };
    

    例4-1 状态继承:

    let task=new Dispatcher((trigger_success)=>{
        trigger_success(100);
    });
    
    task.register().register().register().register((data)=>{
        console.log(data);
    });
    
    task.execute();
    

    输出:

    100

    例4-2 链式操作:

    let task1=new Dispatcher((trigger_success,trigger_error)=>
    {
        trigger_success();
    });
    
    // register 注册状态
    task1.register(()=>
    {
        console.log("task1 executed.");
    
        return new Dispatcher((trigger_success,trigger_error)=>
        {
            setTimeout(()=>
            {
                trigger_success();
            },2000)
        });
    }).register(()=>
    {
        console.log("task2 executed after 2s.");
    });
    
    task1.execute(); // 启动任务后,register注册态转查询态
    
    // register 查询状态
    task1.register(()=>
    {
        return new Dispatcher((trigger_success,trigger_error)=>
        {
            trigger_success();
        });
    }).register(()=>
    {
        console.log("task3 executed.");
    });
    

    输出:

    task1 executed.
    task3 executed.
    task2 executed after 2s.

    五、catch()异常捕获


    catch()可以看作register()的变形,用于捕获任务异常。

    Dispatcher.prototype.catch=function(on_catch){
        return this.register(null,on_catch);
    };
    

    稍作修改也可以用于捕获运行时异常。

    Dispatcher.prototype.execute=function(){
        const trigger_success=(data)=>{
            this.trigger("success",data);
        };
    
        const trigger_error=(data)=>{
            this.trigger("error",data);
        };
    
        try
        {
            this.task(trigger_success,trigger_error);
        }
        catch(e)
        {
            trigger_error(e);
        }
    };
    

    五、“去掉”execute()接口


    由于已经实现了延迟注册响应,execute()已经没有显式调用的意义了,反正监听器什么时候注册都会得到响应,分发器在构造的时候顺便就把任务启动得了。
    现在把execute()接口改为私有(private),只在内部调用,由于私有、公有(public)的概念对JavaScript意义不大,这里就当看不见好了。

    function Dispatcher(task)
    {
        if(typeof task!=="function")
        {
            throw Error("task is not a function.");
        }
    
        this.state="pending"; // 维护状态
        this.result=undefined; // 缓存task执行结果
    
        this.task=task;
        this.listeners=[];
    
        this.execute(); // *** 启动任务 ***
    };
    
    

    register()接口处于什么职责状态由任务执行时长确定,任务等待外部资源(如AJAX)的时间足够长,所有监听器都会被缓存。

    接口register()不需要显式调用execute()了。

    // 回调函数给与了默认指定,确保注册的同时返回新的分发器
    // 自定义任务内容在需要在回调中实现并返回
    Dispatcher.prototype.register=function(on_success=Dispatcher.prototype.on_success,on_error=Dispatcher.prototype.on_error){
        let next; // 下一个分发器
    
        const noop=(trigger_success,trigger_error)=> // 默认的空任务实现
        {
            switch(this.state) // 本级状态,注意指针,该函数修改下一个分发器的状态
            {
                case "success":
                {
                    if(on_success===Dispatcher.prototype.on_success) // 是否实现了回调
                    {
                        trigger_success(this.result); // 继承上一级状态数据,下一级state修改为success
                    }
                    else
                    {
                        trigger_success(); // 已实现,回调下一级on_success
                    }
                }
                    break;
                case "error":
                {
                    if(on_error===Dispatcher.prototype.on_error) // 是否实现了回调
                    {
                        trigger_error(this.result); // 没有实现就继续路由
                    }
                    else
                    {
                        trigger_success(); // 已实现,可认为异常已处理,回调下一级on_success
                    }
                }
            }
        };
    
        switch(this.state)
        {
            case "pending":
            {
                next=new Dispatcher(noop); // 默认分发器
    
                this.listeners.push({
                    on_success,
                    on_error,
                    dispatcher:next // 缓存默认值
                });
            }
                break;
            case "success":
            {
                if(typeof on_success==="function")
                {
                    next=on_success(this.result); // 产生下一级分发器
                    if(!next|| typeof next.register!=="function") // 返回结果是否具有分发器特征
                    {
                        next=new Dispatcher(noop);
                    }
                }
            }
                break;
            case "error":
            {
                if(typeof on_error==="function")
                {
                    next=on_error(this.result);
                    if(!next|| typeof next.register!=="function") // 返回结果是否具有分发器特征
                    {
                        next=new Dispatcher(noop);
                    }
                }
            }
                break;
        }
    
        return next;
    };
    

    由于分发器构造的时候就立即开始任务,被缓存的下一级分发器已经执行完task而上下文都还未切换,被缓存的分发器执行的是“空任务”,不会改变状态,监听器是不会被触发的,因此trigger()接口内还需要保留显式调用execute()

    去掉execute()显式调用后,再执行一下例4-2,结果是一样的。

    let task1=new Dispatcher((trigger_success,trigger_error)=>
    {
        trigger_success();
    });
    
    task1.register(()=>
    {
        console.log("task1 executed.");
    
        return new Dispatcher((trigger_success,trigger_error)=>
        {
            setTimeout(()=>
            {
                trigger_success();
            },2000)
        });
    }).register(()=>
    {
        console.log("task2 executed after 2s.");
    });
    
    task1.register(()=>
    {
        return new Dispatcher((trigger_success,trigger_error)=>
        {
            trigger_success();
        });
    }).register(()=>
    {
        console.log("task3 executed.");
    });
    

    输出:

    task1 executed.
    task3 executed.
    task2 executed after 2s.

    Dispatcher.js

    function Dispatcher(task)
    {
        if(typeof task!=="function")
        {
            throw Error("task is not a function.");
        }
    
        this.state="pending"; // 维护状态
        this.result=undefined; // 缓存task执行结果
    
        this.task=task;
        this.listeners=[];
    
        this.execute();
    };
    
    // 默认的监听器回调实现,用于确保register有返回值,on_success/on_error没有显式被实现可以变相理解为采用了默认实现
    // 回调函数返回一个默认实现的分发器,分发器的任务实现就是继承状态和结果(adopt its state),是状态传递的基础
    Dispatcher.prototype.on_success=function(data){
        return new Dispatcher(function(trigger_success,trigger_error){
            trigger_success(data); //继承状态 ‘success’和结果,两者应当同时继承
        });
    };
    
    // 见上,默认的on_error实现
    Dispatcher.prototype.on_error=function(data){
        return new Dispatcher(function(trigger_success,trigger_error){
            trigger_error(data);
        });
    };
    
    Dispatcher.prototype.catch=function(on_catch){
        return this.register(null,on_catch);
    };
    
    // 回调函数给与了默认指定,确保注册的同时返回新的分发器
    // 自定义任务内容在需要在回调中实现并返回
    Dispatcher.prototype.register=function(on_success=Dispatcher.prototype.on_success,on_error=Dispatcher.prototype.on_error){
        let next; // 下一个分发器
    
        const noop=(trigger_success,trigger_error)=> // 默认的空任务实现
        {
            switch(this.state) // 本级状态,注意指针,该函数修改下一个分发器的状态
            {
                case "success":
                {
                    if(on_success===Dispatcher.prototype.on_success) // 是否实现了回调
                    {
                        trigger_success(this.result); // 继承上一级状态数据,下一级state修改为success
                    }
                    else
                    {
                        trigger_success(); // 已实现,回调下一级on_success
                    }
                }
                    break;
                case "error":
                {
                    if(on_error===Dispatcher.prototype.on_error) // 是否实现了回调
                    {
                        trigger_error(this.result); // 没有实现就继续路由
                    }
                    else
                    {
                        trigger_success(); // 已实现,可认为异常已处理,回调下一级on_success
                    }
                }
            }
        };
    
        switch(this.state)
        {
            case "pending":
            {
                next=new Dispatcher(noop); // 默认分发器
    
                this.listeners.push({
                    on_success,
                    on_error,
                    dispatcher:next // 缓存默认值
                });
            }
                break;
            case "success":
            {
                if(typeof on_success==="function")
                {
                    next=on_success(this.result); // 产生下一级分发器
                    if(!next|| typeof next.register!=="function") // 返回结果是否具有分发器特征
                    {
                        next=new Dispatcher(noop);
                    }
                }
            }
                break;
            case "error":
            {
                if(typeof on_error==="function")
                {
                    next=on_error(this.result);
                    if(!next|| typeof next.register!=="function") // 返回结果是否具有分发器特征
                    {
                        next=new Dispatcher(noop);
                    }
                }
            }
                break;
        }
    
        return next;
    };
    
    Dispatcher.prototype.trigger=function(type,data){
        function switchContext(cache,next)
        {
            // 返回值是否具有分发器特征
            if(typeof next.register==="function")
            {
                cache.task=next.task; // 替换上下文
    
                next.task=null;
            }
        }
    
        this.state=type;
        this.result=data;
    
        switch(type)
        {
            case "success":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_success==="function")
                    {
                        let implement=listener.on_success(data); // 接受自定义实现
                        let deferred=listener.dispatcher;
    
                        if(implement&& typeof implement.register==="function")
                        {
                            switchContext(deferred,implement); // 替换上下文
                        }
                        deferred.execute(); // 执行自定义的task
                    }
                });
            }
                break;
            case "error":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_error==="function")
                    {
                        let implement=listener.on_error(data);
                        let deferred=listener.dispatcher;
    
                        if(implement&& typeof implement.register==="function")
                        {
                            switchContext(deferred,implement);
                        }
                        deferred.execute();
                    }
                });
            }
                break;
        }
    };
    
    Dispatcher.prototype.execute=function(){
        const trigger_success=(data)=>{
            this.trigger("success",data);
        };
    
        const trigger_error=(data)=>{
            this.trigger("error",data);
        };
    
        try
        {
            this.task(trigger_success,trigger_error);
        }
        catch(e)
        {
            trigger_error(e);
        }
    };
    

    六、Promise


    Promise原理与事件分发同源,但语义与事件分发、观察者模式等差太远,不容易直接理解。
    Dispatcher.register类似Promise.thenPromise.then延迟注册响应的特点会让人产生Promise对象可以并行执行的错觉。

    打开文本编辑器,对Dispatcher代码进行一些文本替换,就是一个简陋的Promise

    Promise.js

    function Promise(task)
    {
        if(typeof task!=="function")
        {
            throw Error("task is not a function.");
        }
    
        this.state="pending";
        this.result=undefined;
    
        this.task=task;
        this.listeners=[];
    
        this.execute();
    };
    
    Promise.prototype.on_resolve=function(data){
        return new Promise(function(resolve,reject){
            resolve(data);
        });
    };
    
    Promise.prototype.on_reject=function(data){
        return new Promise(function(resolve,reject){
            reject(data);
        });
    };
    
    Promise.prototype.catch=function(on_catch){
        return this.then(null,on_catch);
    };
    
    Promise.prototype.then=function(on_resolve=Promise.prototype.on_resolve,on_reject=Promise.prototype.on_reject){
        let next;
    
        const noop=(resolve,reject)=>
        {
            switch(this.state)
            {
                case "resolved":
                {
                    if(on_resolve===Promise.prototype.on_resolve)
                    {
                        resolve(this.result);
                    }
                    else
                    {
                        resolve();
                    }
                }
                    break;
                case "rejected":
                {
                    if(on_reject===Promise.prototype.on_reject)
                    {
                        reject(this.result);
                    }
                    else
                    {
                        resolve();
                    }
                }
            }
        };
    
        switch(this.state)
        {
            case "pending":
            {
                next=new Promise(noop);
    
                this.listeners.push({
                    on_resolve,
                    on_reject,
                    promise:next
                });
            }
                break;
            case "resolved":
            {
                if(typeof on_resolve==="function")
                {
                    next=on_resolve(this.result);
                    if(!next|| typeof next.then!=="function")
                    {
                        next=new Promise(noop);
                    }
                }
            }
                break;
            case "rejected":
            {
                if(typeof on_reject==="function")
                {
                    next=on_reject(this.result);
                    if(!next|| typeof next.then!=="function")
                    {
                        next=new Promise(noop);
                    }
                }
            }
                break;
        }
    
        return next;
    };
    
    Promise.prototype.trigger=function(type,data){
        function switchContext(cache,next)
        {
            if(typeof next.then==="function")
            {
                cache.task=next.task;
    
                next.task=null;
            }
        }
    
        this.state=type;
        this.result=data;
    
        switch(type)
        {
            case "resolved":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_resolve==="function")
                    {
                        let implement=listener.on_resolve(data);
                        let deferred=listener.promise;
    
                        if(implement&& typeof implement.then==="function")
                        {
                            switchContext(deferred,implement);
                        }
                        deferred.execute();
                    }
                });
            }
                break;
            case "rejected":
            {
                this.listeners.forEach((listener)=>{
                    if(typeof listener.on_reject==="function")
                    {
                        let implement=listener.on_reject(data);
                        let deferred=listener.promise;
    
                        if(implement&& typeof implement.then==="function")
                        {
                            switchContext(deferred,implement);
                        }
                        deferred.execute();
                    }
                });
            }
                break;
        }
    };
    
    Promise.prototype.execute=function(){
        const resolve=(data)=>{
            this.trigger("resolved",data);
        };
    
        const reject=(data)=>{
            this.trigger("rejected",data);
        };
    
        try
        {
            this.task(resolve,reject);
        }
        catch(e)
        {
            reject(e);
        }
    };
    

    例6-1:

    new Promise(function(resolve,reject){
        console.log('p1 resolved.');
        resolve(100);
    }).then(function(){
        return new Promise(function(resolve,reject){
            setTimeout(function(){
                console.log('p2 rejected.');
                reject(200);
            },2000);
        });
    }).then(function(){
        return new Promise(function(resolve,reject){
            console.log('p3 resolved.');
            resolve(300);
        });
    }).then().then().then(function(data){
        console.log('data: '+data+" after 2s.");
    }).catch().catch().catch(function(error){
        console.log('error: '+error+" after 2s.");
    }).then(function(){
        console.log(500);
    },function(){
        console.log(400);
    });
    

    输出:

    p1 resolved.
    p2 rejected.
    error: 200 after 2s.
    500

    相关文章

      网友评论

        本文标题:快速理解Promise

        本文链接:https://www.haomeiwen.com/subject/efucbftx.html