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有以下几种状态:

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

  • fulfilled: 意味着操作成功完成。

  • rejected: 意味着操作失败。

使用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实例状态的变化

只有两种变化过程,而且变化之后之后不会发生变化,会保持状态的一致
只能从 _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对象的错误信息作为它的失败错误信息。

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

用来控制请求超时

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


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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值