promise

作者: JuanitaLee | 来源:发表于2019-01-19 17:29 被阅读113次

    什么是Promise

    Promise是抽象异步处理对象以及对其进行各种操作的组件。 其详细内容在接下来我们还会进行介绍,Promise并不是从JavaScript中发祥的概念。

    Promise最初被提出是在 E语言中, 它是基于并列/并行处理设计的一种编程语言。

    现在JavaScript也拥有了这种特性,这就是本书所介绍的JavaScript Promise。

    另外,如果说到基于JavaScript的异步处理,我想大多数都会想到利用回调函数。

    Promise解决的问题


    我相信每个前端都遇到过这样一个问题,当一个异步任务的执行需要依赖另一个异步任务的结果时,我们一般会将两个异步任务嵌套起来,这种情况发生一两次还可以忍,但是发生很多次之后,你的代码就会变成这个熊样:

        async1(function(){
            async2(function(){
                async3(function(
                    async4(funciton(){
                        async5(function(){
                            //(╯°□°)╯︵┻━┻
                            //...
                        });
                    });
                )); 
            });
        });
    

    这就是所谓的回调地狱,代码层层嵌套,环环相扣,很明显,逻辑稍微复杂一些,这样的程序就会变得难以维护。

    但去年ES2015的标准里,Promise的标准化,一定程度上解决了JavaScript的流程操作问题。

    Promise的基本用法


    Promise类似于 XMLHttpRequest,从构造函数 Promise 来创建一个新建新promise对象作为接口。

    要想创建一个promise对象、可以使用new来调用Promise的构造器来进行实例化。

    我们新建一个Promise的实例:

    var _promise = new Promise(function(resolve, reject){
      setTimeout(function(){
        var rand = Math.random();
        if(rand<0.5){
            resolve("resolve"+rand);
        }else{
            reject("reject"+rand);
        }
      }, 1000)
    })
    

    运行结果有两种情况,如下图


    运行结果

    先跟大家介绍一下Promsie的基础知识
    Promise对象有三种状态,他们分别是:

    • pending:等待中或者进行中,表示还没得到结果
    • resolve(fulfilled):已经完成,表示得到了我们想要的结果,可以继续往下执行
    • rejected:也表示得到结果,但是由于结果并非我们希望的,因此拒绝执行
      这三种状态不受外界影响,而且状态只能从pending改变为resolved或者rejected,并且不可逆。

    在Promise对象的构造函数中,接受一个函数作为参数,该函数就是用来处理Promise的状态变化的,该函数接受两个额外的函数resolve和reject,这两个函数分别代表将当前Promise置为fulfilled(解决)和rejected(拒绝)两个状态。

    实际上Promise实例_promise是一个对象,不是一个函数。在声明的时候,Promise传递的参数函数会理解执行,因此Promise使用的正确姿势是在其外层再包裹一层函数。如下:

    var run = funciton(){
      var _promise = new Promise(function(resolve, reject){
        setTimeout(function(){
          var rand = Math.random();
          if(rand<0.5){
              resolve("resolve"+rand);
          }else{
              reject("reject"+rand);
          }
        },1000)
      })
      return _promise;
    }
    run();
    

    这是Promise的正常用法

    一个Promise必须提供一个then方法来获取其值或原因。
    Promise的then方法接受两个参数:promise.then(onFulfilled, onRejected)

    then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

    接着上面创建的函数run(),我们来进行对异步操作结果的处理:

    run().then(function(data){
      //处理resolve的代码
      console.log("Promise被置为resolve",data);
    }, function(data){
      //处理reject的代码
      console.log("Promise被置为reject",data);
    })
    

    如果异步操作获得了我们想要的结果,那我们将调用处理resolve的函数(即onFulfilled方法),也就是在then的第一个作为参数的函数中进行处理,获取数据;如果我们得到了错误的结果,调用处理reject的函数(即 onRejected方法),也就是在then函数的第二个作为参数的函数中进行处理,获取错误处理数据。

    reject后的处理,除了可以在.then 的第二个参数 或者是在 .catch 方法中设置想要调用的函数。

    以下是将对reject的处理放到.catch方法中:

    run().then(function(data){
      //处理resolve的代码
      console.log("Promise被置为resolve",data);
    }).catch(function(data){
      //处理reject的代码
      console.log("Promise被置为reject",data);
    })
    

    这样,一个次完整的Promise调用就结束了。对于Promise的then()方法,then总是会返回一个Promise实例:
    promise2 = promise1.then(onFulfilled, onRejected);
    因此我们可以像上面面那样接着对其返回值进行 .then 调用,形如run().then().then().then().then().then().....
    在一个then()方法调用异步处理成功的状态时,你既可以return一个确定的“值”,也可以再次返回一个Promise实例,当返回的是一个确切的值的时候,then会将这个确切的值传入一个默认的Promise实例,并且这个Promise实例会立即置为fulfilled状态,以供接下来的then方法里使用。如下所示:

        run().then(function(data){
            console.log("第一次",data);
            return data;
        }).then(function(data){
            console.log("第二次",data);
            return data;
        }).then(function(data){
            console.log("第三次",data);
            return data;
        });
        /* 异步处理成功的打印结果:
            第一次 resolve0.49040459200760167d.js:18 
            第二次 resolve0.49040459200760167d.js:21 
            第三次 resolve0.49040459200760167
            由此可知then方法可以无限调用下去。
        */
    
    

    根据这个特性,我们就可以将相互依赖的多个异步逻辑,进行顺序管理。
    下面举个例子:

    //第一个异步任务
    function run_a(){
     return new Promise(function(resolve,reject){
          //假设已经进行了异步操作,并获得了数据
          resolve("step1");
      })
    }
    //第二个异步任务
    function run_b(){
     return new Promise(function(resolve,reject){
          //假设已经进行了异步操作,并获得了数据
          resolve("step2");
      })
    }
    //第三个异步任务
    function run_c(){
     return new Promise(function(resolve,reject){
          //假设已经进行了异步操作,并获得了数据
          resolve("step3");
      })
    }
    
    //连续调用
    run_a().then(function(data){
      //返回一个Promise实例
      return run_b(data);
    }).then(function(data){
      return run_c(data);
    }).then(function(data){
      console.log(data);
    })
    

    用 async/await 来处理异步

    相关文章

      网友评论

          本文标题:promise

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