zoukankan      html  css  js  c++  java
  • ES6新特性之 promise

      新的ES6中引入了promise的概念,其目的是让回调更为优雅。层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用。于是Promise就应运而生。Promise即承诺的意思,new一个Promise就是新建一个承诺。在新建一个承诺的时候你需要做两件事情:

      1.指定承诺所需完成的事

      2.设置承诺是否实现的标准

    下面我们来定义一个承诺:

      1.承诺的内容:“获取data.php的数据”,

      2.承诺是否实现的评判是:是否获取data.php的数据 ”

    这里我们会用到jQuery.ajax()方法,这会让我们的代码显得简单精炼。

    var http = {
        get: function(url) {
            var promise = new Promise(function(resolve, reject) {
                $.ajax({
                    url: url,
                    method: 'get',
                    success: function(data) {
                        resolve(data);
                    },
                    error: function(xhr, statusText) {
                        reject(statusText);
                    }
                });
            });
            return promise;
        }
    };
    http.get('data.php').then(function(data) {
        document.write(data);
    }, function(err) {
        document.write(err);
    });
    /* 待获取的data.php文件 */
    <?php
    echo '{"name":"Tom","age":"22"}';

      在http请求中,我们定义了一个get方法,在get方法中,我们定义了一个promise的对象,而不是直接直接使用ajax获取到我们想要的数据,在这个get方法,我们最后得到的是一个promise对象,对于这种需要等待的操作,我们采用promise去处理,返回给主线程的是一个promise对象,而不是一个最终的数据,这是延迟程序给主程序的一个承诺,主线程可以根据通过返回的promise对象获取数据或者处理错误。这使得异步处理变得优雅而简单。

      在jQuery.ajax()中,我们采用了两个方法来判断是否实现了我们的承诺,它们分别是resove和reject方法,如果如果jQuery.ajax()执行了success,并且返回的data中有数据,那么我们就判定这个承诺已经实现了(fulfilled),则调用resolve方法。如果jQuery.ajax()执行了error,那么我们就判定这个承诺被拒绝了(rejected),则调用reject方法。

    那resove和reject这两个方法分别执行了哪些操作呢?这个我们就需要从Promise这个构造函数本身的结构说起。Promise这个构造函数结构大概是下面这样的:

    /* 用于描述思维的代码 */
    function Promise(executor) {
        // 共有三种状态:pending(准备)、fulfilled(完成)、rejected(拒绝)
        this.PromiseStatus = 'pending';
        // 用于存储返回的数据
        this.PromiseValue;
        // 完成
        var resolve = function(reson) {};
        // 拒绝
        var reject = function(reson) {};
        ...
        // 开始执行承诺
        executor(resolve, reject);
    }
    Promise.prototype.then = function() {};
    Promise.prototype.chain = function() {};
    Promise.prototype.catch = function() {};
    ...

    PromiseStatus:用于记录Promise对象的三种状态,这三中状态分别是:
    pending:待定状态,Promise对象刚被初始化的状态
    fulfilled:完成状态,承诺被完成了的状态
    rejected:拒绝状态,承诺完成失败的状态
    Promise的初始状态是pending。随后会更具承诺完成的情况更改PromiseStatus的值。

    PromiseStatus:用于记录返回的数据或者错误。当承诺完成时,会把返回的数据赋给PromiseStatus。如果承诺执行失败了,那么失败的原因也会赋给此变量。

    resolve()和reject():Promise构造函数中有两个闭包的函数resolve()和reject()。在new一个新的Promise的时候会传递一件你需要做的事情(executor)。这个executor是一个函数,在Promise的构造函数中它会被传入两个参数,这两个参数即我们的两个闭包的函数resolve()和reject(),以便你在executor中判定是否完成了你的承诺。

    executor(): executor()函数中执行的代码就是子程序需要完成事。在executor()函数内如果调用了resolve(),resolve()则会把Promise对象的状态PromiseStatus修改为fulfilled,把resolve(value)中的value值赋给Promise对象的PromiseValue。然后再依次执行由then()方法构成的回调链中的回调函数。同样,在executor()中调用reject()的过程也是类似的。调用过程如下:

    /* 用于描述思维的代码 */
    executor(resolve, reject) {
        ...
        resolve(value);
        ...
    }
    ...
    resolve(value) {
        PromiseStatus = 'fulfilled';
        PromiseValue = value;
        ...
        // 接着调用回调链中的回调函数
    }

      

    then(onFulfilled, onRejected):这个方法实际上是把onFulfilled()函数和onRejected()函数添加到Promise对象的回调链中。回调链就像一个由函数组构成的队列,每一组函数都是由至少一个函数构成(onFulfilled() 或者 onRejected() 或者 onFulfilled() 和 onRejected())。当resolve()或者reject()方法执行的时候,回调链中的回调函数会根据PromiseStatus的状态情况而被依次调用。

    onFulfilled(value)和onRejected(reason):参数value和reason的实参都是PromiseValue。这里有一点值得注意,如果onFulfilled(value)和onRejected(reason)这两个回调函数中return返回值不是一个Promise的对象,那么这个返回值会被赋给PromiseValue,并在下一个then()的onFulfilled(value)和onRejected(reason)中做为实参使用。但如果这个返回值是一个Promise的对象,那么剩下的由then()构造的回调链会转交给新的Promise对象并完成调用。

    有这样一个问题,如果在第一个then()中执行了onRejected(reason)回调函数,并且没有return任何值的时候,那么下一个then()中将会调用onFulfilled(value)方法,而不是onRejected(reason)。因为在执行上一个then()的onRejected(reason)回调函数的时候并没有出现错误或异常,所以PromiseStatus的状态就被更改为fulfilled了。为了避免这个问题,我们可以在onRejected(reson)中返回一个Promise对象并reject()。代码如下,我们要去访问一个并不存在的文件solve.php:

    var http = {
        get: function(url) {
            var promise = new Promise(function(resolve, reject) {
                $.ajax({
                    url: url,
                    method: 'get',
                    success: function(data) {
                        resolve(data);
                    },
                    error: function(xhr, statusText) {
                        reject(statusText);
                    }
                });
            });
            return promise;
        }
    };
    http.get('solve.php').then(function(data) {
        return data;
    }, function(err) {
        return Promise.reject('Sorry, file not Found.');
    }).then(function(data) {
        document.write(data);
    }, function(err) {
        document.write(err);
    });

     Promise.reject()方法会返回一个被reject()的Promise对象,因此使得我们可以继续走下一个then()中的onRejected(reason)方法。

  • 相关阅读:
    python 之字符编码
    python文件处理
    迭代器和生成器
    内置函数和匿名函数
    函数之递归
    函数 之装饰器
    python 函数进阶与闭包
    python 之 函数
    python之运算符
    python字符串内置方法
  • 原文地址:https://www.cnblogs.com/hanguidong/p/9497461.html
Copyright © 2011-2022 走看看