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)方法。

  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/hanguidong/p/9497461.html
Copyright © 2011-2022 走看看