Promise

作者: ag4kd | 来源:发表于2019-11-08 14:32 被阅读0次

    本文根据promise英文规范以及ES6源码 总结。本文拙见,欢迎斧正

    这两天学习了一下 nodejs.

    看到异步这一块时,百度以下Promise,发现多篇一律如下图:

    image.png image.png

    单线程或者多线程,跟异步没有必然的因果关系。网络和文件读写这种耗时操作才跟异步有关。多线程用来提高系统资源的利用率,异步来解决耗时任务,二者天生就没有必然的因果关。即使JS支持多线程,你也需要异步执行耗时操作,因为多线程的行为表现为异步的,你不知道这个线程啥时候执行完。

    看到这两句话:

    JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。

    由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。

    就没有再读下去的心思了,多线程只是异步操作的的一种体现方式。所以不能说单线程缺陷导致必须使用异步。

    使用异步完全是因为操作耗时,会造成界面卡顿、无响应等

    还是promise英文规范最靠谱。

    IDE:WebStorm

    ES6

    前言

    promise是一个健全的,可互操作的开放标准,由实现者为实现者。

    promise表示异步操作的最终结果。与promise交互的主要方式是通过其then方法,该方法注册回调函数以接收的promise的最终值或promise无法实现的原因。

    该规范详细描述了then方法的行为,提供了一个可交互的基础,所有承诺/A+符合承诺的实现都可以依赖于此基础来提供。因此,应该认为该规范非常稳定。虽然promise /A+组织可能偶尔会修改这个规范,对它进行一些向后兼容的小修改,以解决新发现的问题,但是我们只有在仔细考虑、讨论和测试之后,才会集成大型的或向后不兼容的修改。

    历史上,promise /A+澄清了较早的promise /A提案中的行为条款,将其扩展到涵盖实际行为,并省略了未指定或有问题的部分。

    最后,核心promise /A+规范不处理如何创建、实现或拒绝承诺,而是选择专注于提供一个互操作的 then方法。未来在配套规范中的工作可能会涉及这些主题。

    术语

    • promise:是一个带有then方法的对象或者一个函数,其行为遵循promise /A+规范。
    • thenable:是一个对象或者一个函数,定义then方法。
    • value:一个合法的js类型的值,如undefined, a thenable, or a promise
    • exception:异常。
    • reason:绝句执行的原因。

    三种状态

    • pending:可能转变完成或者拒绝。
    • fulfilled:不能转变为其他状态,只能是一个不能改变value
    • rejected:不能转变为其他状态,只能是一个不能改变reason

    在这里,不能改变意味着不变的身份(即===),但并不意味着深度不变。

    then方法

    定义回调函数,用来接收异步任务的结果。
    源码:

    interface PromiseLike<T> {
        /**
         * Attaches callbacks for the resolution and/or rejection of the Promise.
         * @param onfulfilled The callback to execute when the Promise is resolved.
         * @param onrejected The callback to execute when the Promise is rejected.
         * @returns A Promise for the completion of which ever callback is executed.
         */
        then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) =>
         TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: 
         ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): 
         PromiseLike<TResult1 | TResult2>;
    }
    

    一个promise必须提供一个then方法来访问它当前或最终的值或原因。promise的then方法接受两个参数:

    promise.then(onFulfilled, onRejected)
    

    参数含义

    • onFulfilled成功的回调,可选参数。
    • 如果不是函数,则被忽略。
    • 如果是个函数,则在promise执行成功被回调,promise’svalue会作为第一个参数传递,其实就是resolve();的一个实现方法。

    • onRejected失败的回调,可选参数,如果不是函数,则被忽略。
    • 如果是个函数,则在promise拒绝执行被回调,promise’sreason会作为第一个参数传递,其实就是reject();的一个实现方法。。

    如果要回调,这两个参数必须是一个函数:

    new Promise.then(function () {
    
    },function () {
        
    });
    

    回调时机

    onFulfilledonRejected 只有在执行环境堆栈仅包含平台代码时才可被调用!说白了,就是通过resolve或者reject``,来执行回调逻辑。

    正常业务逻辑下需要调用resolve("参数");方法去触发回调函数onFulfilled的执行;异常逻辑需要throw一个异常Error或者通过reject();方法来触发onRejected的执行。否则不执行回调!

    then一定返回一个promise

    实现链式调用的基础

    promise2 = promise1.then(onFulfilled, onRejected);
    

    简单的案例

    then源码声明:

     /**
         * Attaches callbacks for the resolution and/or rejection of the Promise.
         * @param onfulfilled The callback to execute when the Promise is resolved.
         * @param onrejected The callback to execute when the Promise is rejected.
         * @returns A Promise for the completion of which ever callback is executed.
         */
        then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) =>
         TResult1 | PromiseLike<TResult1>) | undefined | null, onrejected?: 
         ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined | null): 
         Promise<TResult1 | TResult2>;
    

    catch 源码(声明):

    
        /**
         * Attaches a callback for only the rejection of the Promise.
         * @param onrejected The callback to execute when the Promise is rejected.
         * @returns A Promise for the completion of the callback.
         */
        catch<TResult = never>(onrejected?: ((reason: any) => 
        TResult | PromiseLike<TResult>) | undefined | null): Promise<T | TResult>;
    

    没有出现错误或异常的代码

    function promise() {
        let promise = new Promise(function (resolve, reject) {
            console.log("处理具体业务");
            resolve("参数");//
        }).then(function (value) {
            console.log("处理成功 " + value);
        }, function () {
            console.log("处理失败");
        }).catch(function () {
            console.log("处理异常");
        });
    }
    
    promise();
    
    image.png

    出现错误或异常的代码

    function promise() {
        let promise = new Promise(function (resolve, reject) {
            try {
                console.log("处理具体业务");
                ass();//未定义函数
                console.log("处理具体业务,异常代码之后");
                resolve("参数");//
            } catch (e) {
                throw new Error("dddd");
                // reject();
            }
        }).then(function (value) {
            console.log("处理成功 " + value);
        }, function () {
            console.log("处理失败");
        }).catch(function () {
            console.log("处理异常");
        });
    }
    promise();
    

    程序调用了一个未定义的函数ass();,然后,走catch{}块,在这个捕获异常的代码块里面,执行reject();或者抛出一个错误,如果then方法的第二个参数是函数,则会走这个回调函数,如果没有定义第二个回调函数而是定义了一个catch代码块,则会走catch代码块,如果即定义了回调函数,又调用了异常处理函数catch代码块,则只会有回调函数,如果二者都没有,则程序会报错,以下是未实现回调函数而调用了异常处理函数。

    本质上,是有调用了只有声明而没有实现的函数。

    1、异常没有被开发者实现:


    image.png

    2、reject();没有被开发者实现:

    image.png

    总之,至少要有一个能够异常或者的回调逻辑。

    可以被回调多次的then

    function doing(value) {
        return new Promise(function (resolve, reject) {
            try {
                console.log(value);
                resolve(value);//
                // resolve();//
            } catch (e) {
                // throw new Error("dddd");
                reject(value);
            }
        });
    }
    
    function do_something_wrong(value) {
        return new Promise(function (resolve, reject) {
            try {
                console.log(value + "级业务");
                // ass();
                // reject("业务逻辑异常");
                resolve(value);//
                // resolve();//
            } catch (e) {
                // throw new Error("dddd");
                reject(value);
            }
        });
    }
    
    function promise() {
        let promise = new Promise(function (resolve, reject) {
            try {
                console.log("一级业务");
                ass();
                console.log("处理具体业务,异常代码之后");
                resolve(1);//
            } catch (e) {
                // throw new Error("dddd");
                reject(2);
            }
        }).then(function (value) {
            doing("二级业务");
        }, function (error) {
            do_something_wrong("二级业务----处理一级异常");
        }).then(function (value) {
            doing("三级业务");
        }, function (value) {
            do_something_wrong("三级业务----处理一级异常");
        }).then(function (value) {
            doing("四级业务");
        }, function (value) {
            do_something_wrong("四级业务----处理一级异常");
        }).then(function (value) {
            doing("五级业务");
        }, function (value) {
            do_something_wrong("五级业务----处理一级异常");
        }).then(function (value) {
            doing("六级业务");
        }, function (value) {
            do_something_wrong("六级业务----处理一级异常");
        });
        return promise;
    }
    
    promise();
    
    image.png

    英文原文说:

    If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.
    
    If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.
    
    • promise 成功执行时,所有 onFulfilled 需按照其链式调用的顺序依次回调。
    • promise 被拒绝执行时,所有的 onRejected 需按照其链式调用的顺序依次回调。

    相关文章

      网友评论

          本文标题:Promise

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