详解Promise对象

Promise接口

es6将Promise写入语言标准,因此目前js原生支持Promise对象。使用Promise的优点就不赘述了,Promise对象起到一个代理的作用(proxy),它充当异步操作和回调函数之间的中介。它的思想是,每一个异步任务立刻返回一个Promise对象,由于是立即返回,所以和同步流程没有区别。Promise对象使用then方法添加回调函数。then方法可以接受两个回调函数,第一个是异步操作成功时的回调函数,第二个是异步操作失败时的回调函数(可以省略)。一旦状态改变,就调用相应的回调函数。(Promise的构造函数内容下面会细讲)

   new Promise(...).then(
      fn1,
      fn2
   )

上面代码中,Promise对象使用then方法绑定两个回调函数:操作成功时的回调函数fn1,操作失败时的回调函数fn2。这两个函数都接受异步操作传回的值作为参数。如果把这两个函数复杂化一点,伪代码就是这样

   new Promise(...).then(function(value){
      ...    // 逻辑代码
      console.log(value);    
   }, function(error){
      ...    // 逻辑代码
      console.log(error);
   })

接下来我们来看一下Promise的具体应用例子

Promise对象生成

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由js引擎提供,不用自己部署。

   var promise = new Promise(function(resolve, reject){
       //异步操作代码
       if(...){
       //resolve函数有两个作用,第一个是将这个对象的异步操作状态改为成功,第二个是将参数value传入回调函数
           resolve(value);   
       } else {
       //reject函数有两个作用,第一个是将这个对象的异步操作状态改为失败,第二个是将参数error传入回调函数
          reject(error);
       }
   })

这里的value和error,是promise对象传给回调函数的参数,如果成功则传value,失败传error,所以

   var promise = new Promise(function(resolve, reject){
       resolve('success')
   })
   promise.then(function(value){
       console.log(value)   // 'success'
   })

失败的时候

   var promise = new Promise(function(resolve, reject){
       reject('error')
   })
   promise.then(function(value){
       console.log(value)  //不执行,第一个函数是成功的函数
   }, function(error){
       console.log(error)  // 'error'  
   })

当然这里为了方便理解把错误处理函数写在了then中

链式调用

我们要注意,每一次调用then函数之后,返回的还是一个Promise对象

   var promise1 = new Promise(function(resolve, reject){
       resolve('success')   //省略其他逻辑代码
   })
   promise1
      .then(function(value){
          console.log(value)  // 'success'
          return 'success'
      })
      .then(function(value){
          console.log(value)   // 'success'
      })

这里第一个then直接返回success,相当于

   var promise1 = new Promise(function(resolve, reject){
       resolve('success')   //省略其他逻辑代码
   })
   var promise2 = new Promise(function(resolve, reject){
       resolve('success')   //省略其他逻辑代码
   })
   promise1
      .then(function(value){
          console.log(value)  // 'success'
          return promise2;
      })
      .then(function(value){
          console.log(value);   // 'success'
      })

也就是说如果直接在then中return,相当于这个Promise对象的状态改为了已完成,并且把return的值传入了回调函数中。那么如果没有return一个值,那么下一个then函数自然是拿不到的

   promise1
      .then(function(value){
          return;
      })
      .then(function(value){
          console.log(value);   // 'undefined'
      })

那么如果发生了错误呢

   new Promise()
      .then(step1)
      .then(step2)
      .then(step3)
      .then(
        console.log,
        console.error
      );

如果step1出错,返回的Promise对象状态为rejected,接下来的step2就不会再执行了,Promises对象开始寻找,接下来第一个操作失败时的回调函数,于是它找到了console.error,当然推荐的写法是

   promise
      .then(function(data) {
        // success
      })
      .catch(function(err) {
        // error
      });

catch方法可以捕获前面then方法执行中的错误,也更接近同步的写(try/catch) 需要注意的是,catch方法返回的还是一个 Promise 对象,因此后面还可以接着调用then方法。

Promise的一次性

Promise的变化途径只有两种。

  • 异步操作从未完成到已完成
  • 异步操作从未完成到失败
    这种变化只能发生一次,一旦当前状态变为“已完成”或“失败”,就意味着不会再有新的状态变化了,所以在Promise中重复调用resolve和reject没有作用
   var promise = new Promise(function(resolve, reject){
       resolve(...)
       resolve(...)    // 不起作用
   })

你可能感兴趣的:(js异步,Promise,异步,对象,标准,函数)