Promise的学习和使用

语法

new Promise( function(resolve, reject) {...} /* executor */  );
复制代码

executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时当即调用executor 函数, resolve 和 reject 两个函数做为参数传递给executor(executor 函数在Promise构造函数返回新建对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改成_fulfilled(完成)或rejected(失败)。executor 内部一般会执行一些异步操做,一旦完成,能够调用resolve函数来将promise状态改为_fulfilled,或者在发生错误时将它的状态改成rejected。若是在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
一个 Promise有如下几种状态:javascript

  • pending: 初始状态,既不是成功,也不是失败状态。html

  • fulfilled: 意味着操做成功完成。java

  • rejected: 意味着操做失败。ajax

使用promise

let status = 1;
// 判断status是否为1,是1的时候执行成功
let p1 = new Promise(function(resolve,reject){
    if(status==1){
        resolve({msg:"执行成功",status:"200"}); // 这里传递给resolve的数据就是以后then中接受到的res
    }else{
        reject({msg:"执行失败",status:"404"}); // 对应catch中的err
    }
});

p1.then(res=>{
    console.log(res);
}).catch(err=>{
    console.log(err);
})
复制代码

Promise的一些注意点

Promise的理解

promise能够当作是去肯德基买汉堡,先预约一个汉堡,而后收营员会给你一小票并向你承诺以后会给你一个汉堡(也可能汉堡买完了没有汉堡)。从下单到得到汉堡的这个过程能够当作是异步的操做,期间你能够刷一下子手机,同时后厨在准备汉堡。有了汉堡以后吃汉堡(处理resolve),或者没有汉堡了发生退款(处理reject)。
你在等待这个承诺的到来,一旦到来你就能够开始吃汉堡或者没有汉堡遗憾的退款。数组

  • new 出来的Promise对象就是收银员的承诺
  • then 中的第一个回调就是收到汉堡最后吃汉堡的操做
  • then中的第二个回调就是没有汉堡了退款的操做
  • Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的

对于then的理解

then并非处理promise实例返回的resolve状态值,resolvereject状态的值都可以处理,第一个回调函数处理成功,第二个回调函数处理失败,若是缺省第二个处理失败的回调,则状态为rejectpromise传递到下一个链式调用。 promise

Promise实例状态的变化

只有两种变化过程,并且变化以后以后不会发生变化,会保持状态的一致
只能从 _pending -> fulfilled 或者 从 pending -> rejected _一旦状态发生变化就不会再发生改变,保持一致性。(你去买汉堡只可能有两种状态,买到汉堡和没有买到,并且不可能在二者之间变化)异步

  • promise对此调用的结果保持一致,不会发生改变
  • 在Promise的构造调用的时候只能发生一次状态转变,一旦转变以后不会发生变化
var promise = new Promise((resolve, reject) => {
    // 只能改变一次状态
    resolve('1') // 改变状态
    resolve('2') // 不生效
    resolve('3') // 不生效 
    console.log('4') //同步执行
  })
  // 屡次调用promise中的值不会发生变化
  promise.then((data) => {
    console.log('第一个then', data)
  })
  promise.then((data) => {
    console.log('第二个then', data)
  })
// 4
// 第一个then 1
// 第二个then 1
复制代码

then,catch执行以后会返回一个新的promise

  • promise能够链式调用不是由于使用return this, 而是在thencatch以后返回了一个promise
  • then或者catch返回当即值,则返回的promiseresolved状态,至关于Promise.resolve(..)
  • 抛出现异常或者返回Promise.reject(..),则返回的promiserejected状态
var promise = new Promise((resolve, reject) => {
    resolve('1')
  })
  promise.then((data) => {
    console.log(data) // 1
    return 2 // 做为新的promise的resolve值返回
  }).then((data) => {
    // 这里接收的是上一个then返回的新的promise的resolve状态
    console.log(data) // 2
  })
  promise.then((data) => {
    // 能够返回一个promise
    return Promise.reject('错误')
  }).catch((data) => {
    // catch接收上一个then返回的promise
    console.log(data) // 错误, 接收上一个链上的promise的resolve返回
  }).then((data) => {
    console.log(data) // undefined 前一个链上的promise没有返回值
  })

    promise.then((data)=>{
      // 抛出错误
      throw new Error('出错')
    }).catch((err) => {
      // 上一个promise返回的是reject, 内容是 抛出的error
      console.log(err)
    })

// 1
// 2
// Error: 出错
// at promise.then (3.html:32)
// 错误
// undefined
复制代码

异常处理的一些问题

  • 直接经过return new Error('错误')的方式返回异常不能被下一个catch捕获到,这里返回的promiseresolve状态,会被传递下去被then捕获,只有throw new Error()才能被下一个catch捕获
var promise = new Promise((resolve, reject) => {
      resolve('1')
    })

    promise.then((data) => {
      return new Error('错误')
    }).catch((err) => {
      console.log('不会执行')
    }).then((data) => {
      console.log('打印以前返回的错误', data)
    })

    // 打印以前返回的错误 Error: 错误
    // at promise.then (4.html:16)
复制代码
  • then(success, error) then能够由两个处理函数,第一个用来处理resolved状态的promise返回值,第二个用来处理rejected状态的promise返回值,这里处理的是链式调用的返回的前一个promise
var promise = new Promise((resolve, reject) => {
    reject('错误')
  })

  promise.then((data)=>{
    console.log('不会执行,promise状态是rejected')
  }, (err)=>{
    // 捕获到错误
    console.log(err) // 错误
  }).catch((err) => {
    // 链式调用的前一个promise返回是一个resolve状态
    console.log('不能捕获到错误')
  })
复制代码
  • then中没有指定处理rejected状态的函数时,错误状态会一直传递下去直到被处理,要是没有处理不会被window捕获,直接控制台报错...
window.addEventListener('error', (e) => {
      console.log(e)
    })
    var promise = new Promise((resolve, reject) => {
      reject('错误')
    })
    promise.then((data)=>{
      console.log('未对错误处理')
    }).catch((err) => {
      // 执行
      console.log('上一个then中缺省处理错误的函数,错误会被封装成新的promise向下传递', err)
    })
    promise.then((data)=>{
      console.log('不处理,也没有后续,错误会被window捕捉到')
    })
复制代码
  • .then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,然后续的 .catch 能够捕获以前的错误
var promise = new Promise((resolve, rejected) => {
    resolve(1)
  })
  promise.then((data)=>{
    throw new Error('2')
  }, (err) => {
    console.log('不能捕获,then中第一个成功回调返回的错误')
  }).catch((err)=>{
    console.log('能够捕获上一个then中成功或者错误处理函数中抛出的错误')
  })
复制代码

Promise.resolve() 对于传入值的处理

  • 传入一个当即数 如 数字,字符串,则包装成一个新的promise返回
  • 传入的是一个真正的promise,则返回这个promise
  • 传入的是一个thenable的值,则会解封到不是thenable为止
// 传入当即数
Promise.resolve(1).then((data)=>{console.log(data)}) // 1

// 传入promise对象
var p1 = new Promise((resolve,reject) => {
  resolve(2)
})
var p2 = Promise.resolve(p1)
console.log(p1 === p2) // true 返回同一个

// thenable
var o = {
  then:function(cb,err){
    console.log('then函数')
    cb(3)
  }
}
Promise.resolve(o).then((data)=>{console.log(data)}) // then函数 3
复制代码

判断一个函数是否是thenable函数

if(!!p 
   &&
   (typeof p === 'object' || typeof p === 'function')
   &&
   (p.then && typeof p.then === 'function')
  ) { console.log(true)} else {
  console.log('false)
}
复制代码

用来控制请求的执行顺序

Promise.all方法常被用于处理多个promise对象的状态集合。输入是一个由promise对象组成的数组,全部的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则当即触发该promise对象的失败。这个新的promise对象在触发成功状态之后,会把一个包含iterable里全部promise返回值的数组做为成功回调的返回值,顺序跟iterable的顺序保持一致;若是这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息做为它的失败错误信息。ui

这时候能够这样,将一组ajax请求封装成一组promise对象传入Promise.all,返回结果也是有序的,再对这个有序的promise对象进行处理this

用来控制请求超时

Promise.raceiterable参数里的任意一个子promise被成功或失败后,父promise立刻也会用子promise的成功返回值或失败详情做为参数调用父promise绑定的相应句柄,并返回该promise对象。(任意一个成功或者失败就触发)


此时能够构造一个 定时器任务和一个ajax请求,封装成promise对象传入Promise.race,若是定时器的结果先返回,则请求超时

相关文章
相关标签/搜索