es6的Promise详解

Promise

Promise的含义

Promise是异步编程的一种解决方案,比以前传统的异步操作就是回调函数和事件更强大,使用起来更简便,并且避免了回调地狱的问题(回调地狱就是指多层回调函数嵌套)

Promise是es6新增的引用类型,是一个构造函数,通过和关键字new一起使用来创建Promise实例,需要传递一个执行器函数(这个执行器函数是同步执行的),执行器函数有两个参数且都是函数,这两个参数是js提供的不需要我们手动创建

const p = new Promise((resolve,reject) => {
  console.log('我是一个Promise实例')
})
console.log(p)
// 
我是一个Promise实例
Promise { <pending> }  这里为什么是pending后面会讲到
Promise的三种状态
  • 三种状态:
    • 待定(初始)状态:pending
    • 成功(解决)状态:fulfilled
    • 失败(拒绝)状态:rejected
  • 状态转换
    • 两种转换:pending ----> fulfilledpending -----> rejected;有且仅有这两中转换,并且状态一经变化之后就不会在变了
    • 如何转换:通过new Promise初始化时执行器函数的两个参数函数 resolve(pending ----> fulfilled),reject(pending -----> rejected);还可以通过静态方法Promise.resolvePromise.reject来实现状态转换,下面会讲到这两中静态方法;再回到上面那个问题为什么是pending,因为在初始化实例的时候并没有执行resolve和reject这两个当中的任意一个,所以还是处于pending状态

new Promise 转换状态

let p = new Promise((resolve,reject) => {
  resolve('成功')
})
console.log(p)
p = new Promise((resolve,reject) => {
  reject('拒绝')
})
console.log(p)
// 
Promise { '成功' }  // 如果是成功状态则不会在结果里面标出 fulfilled
Promise { <rejected> '拒绝' }
// 下面是 reject 报错
(node:20111) UnhandledPromiseRejectionWarning: 拒绝
(Use `node --trace-warnings ...` to show where the warning was created) ....

静态方法 状态转换 pending —> rejected

let p = new Promise((resolve, reject) => {
})
console.log(p)
p = Promise.reject('fail')
console.log(p)
//
Promise { <pending> }
Promise { <rejected> 'fail' }

pending -----> fulfilled

let p = new Promise((resolve, reject) => {
})
console.log(p)
p = Promise.resolve('fail')
console.log(p)
//
Promise { <pending> }
Promise { 'success' }

状态一经变化后就不会在变了

p = new Promise((resolve, reject) => {
  resolve('success')
  reject('fail')
})
console.log(p)
// 
Promise {'success'}
Promise实例方法
  • Promise.prototype.then

    • 用于给Promise实例添加状态改变时回调函数
    • 最多有两个参数,第一个参数:onResolved处理程序(处理fulfilled状态的回调函数),第二个参数:onRejected处理程序(处理rejected状态的回调函数),由于只能转换一次,所以这两个处理程序是互斥的,只能执行一个
    let fulfilled = new Promise((resolve, reject) => {
      resolve('success')
    })
    let rejected = new Promise((resolve, reject) => {
      reject('fail')
    })
    fulfilled.then(res => console.log('res',res), err => console.log('err',err))
    rejected.then(res => console.log('res',res), err => console.log('err',err))
    // 
    res success
    err fail
    
    • 只需要一个参数的写法
    fulfilled.then((res) => console.log('res',res)) // // res success
    rejected.then(null, (err)=> console.log('err',err)) // err fail
    
    • 函数返回值

    函数返回值是一个Promise实例,但是其状态与他的调用者的状态无关,与then方法的 onResolved处理程序,onRejected处理程序的返回值有关,如果处理程序返回普通值、错误对象和 fulfilled 状态实例就会被Promise.resolve包裹成一个 fulfilled 状态的实例,如果返回的是一个 rejected 实例或抛出异常则返回的是一个 rejected 实例

    处理程序返回普通值、错误对象和 fulfilled 状态实例

    处理程序返回 fulfilled 状态实例其实和普通值一样,只不过就是普通值还需要被包裹成一个 fulfilled 状态实例才能调用下一个then

    //  返回一个 fulfilled 状态实例
    const resolved = Promise.resolve('resolved')
    const p1 = resolved.then(() => Promise.resolve('yes'))
    setTimeout(console.log, 0, 'p1',p1) // p1 Promise { 'yes' }
    
    // 返回一个错误对象,会被包裹成一个 fulfilled 状态实例
    const p3 = resolved.then(res => Error('error'))
    setTimeout(console.log, 0, 'p3',p3)
    //p3 Promise {
    //   Error: error
    //       at /Users/dingjie/practise/js红宝书/Promise/04实例方法then.js:14:33
    // }
    
    // 返回普通值
    const p5 = resolved.then(() => 'success')
    setTimeout(console.log, 0, p5) // Promise { 'success'}
    

    注意:这里为什么不直接使用 console.log而是使用定时器可以参考这篇文章:js执行机制

    处理程序返回 rejected 状态实例 或 抛出异常

    //  返回一个  rejected 状态实例
    const rejected = Promise.reject('rejected')
    const p2 = rejected.then(undefined, () => Promise.reject('no'))
    setTimeout(console.log, 0, 'p2',p2) // p2 Promise { <rejected> 'no' }
    
    //  抛出一个异常,则返回一个  rejected 状态实例
    const p4 = resolved.then(res => {throw 'error'})
    setTimeout(console.log, 0, 'p4',p4) // p4 Promise { <rejected> 'error' }
    
    • 链式调用

    处理程序返回一个普通值会自动包裹成一个 fulfilled 状态实例,自动调用下一个 then,并且将这个普通值作为实参传递给下一个then方法的onResolved处理程序

    返回一个fulfilled 状态实例,自动调用下一个then,并且这个实例的值作为实参传递给下一个then方法的onResolved处理程序

    const p = new Promise((resolve,reject) => {
      resolve('fulfilled')
    })
    p.then(res => res)
    .then((res => 'status:' + res ),(err => console.log('err',err)))
    .then(res => console.log('res',res))
    // 
    res status:fulfilled
    
  • Promise.prototype.catch

    • 只接受一个参数,onRejected处理程序用于处理rejected状态的回调函数
    const rejected = Promise.reject('rejected')
    rejected.catch(res => console.log('res',res))
    //
    res rejected
    
    • 返回值

    返回值:受 onRejected处理程序的返回值影响

    const res = Promise.reject()
    // 返回普通值
    const p1 = res.catch(() => '普通值')
    setTimeout(console.log, 0, p1) // Promise { '普通值' }
    // 返回 fulfilled 状态实例
    const p2 = res.catch(() => Promise.resolve())
    setTimeout(console.log, 0, p2) // Promise { undefined }
    
    // 返回 rejected 状态实例
    const p3 = res.catch(() => Promise.reject())
    setTimeout(console.log, 0, p3) // Promise { <rejected> undefined }
    
    // 抛出错误
    const p4 = res.catch(() => {throw  'error'})
    setTimeout(console.log, 0, p4) // Promise { <rejected> 'error' }
    
  • Promise.prototype.finally

    • finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。常用来做清理操作,或者用来执行 fulfilled 状态和rejected 状态都会执行的操作;它不接受任何参数
    let p = new Promise((resolve,reject)=> {
      resolve(10)
    })
    
    p.then(res=>console.log('resolve',res))
        .catch(res => console.log('reject',res))
        .finally(() => console.log('finally'))
    
    //
    //resolve 10
    //finally
    
    
    p = Promise.reject('100')
    
    p.then(res=>console.log('resolve',res))
        .catch(res => console.log('reject',res))
        .finally(() => console.log('finally'))
    
    // 
    //reject 100
    //finally
    
    
    • 返回值:始终返回原来的值(也可以理解为始终接受来自父(实例对象)的传递),除了这三种情况:返回一个 rejected 状态实例,抛出错误或异常,返回一个 pending 状态实例
    const p1 = Promise.resolve(10).finally(() => 1000)
    const p2 = Promise.resolve(10).finally(() => '10')
    const p3 = Promise.resolve(10).finally(() => undefined)
    const p4 = Promise.resolve(10).finally(() => null)
    const p5 = Promise.resolve(10).finally(() => Promise.resolve(1000))
    const p6 = Promise.resolve(10).finally(() => false)
    const p7 = Promise.resolve(10).finally(() => Error('erroe'))
    
    setTimeout(console.log, 0 , 'p1',p1)
    setTimeout(console.log, 0 , 'p2',p2)
    setTimeout(console.log, 0 , 'p3',p3)
    setTimeout(console.log, 0 , 'p4',p4)
    setTimeout(console.log, 0 , 'p5',p5)
    setTimeout(console.log, 0 , 'p6',p6)
    setTimeout(console.log, 0 , 'p7',p7)
    
    // 
    /**
    p1 Promise { 10 }
    p2 Promise { 10 }
    p3 Promise { 10 }
    p4 Promise { 10 }
    p5 Promise { 10 }
    p6 Promise { 10 }
    p7 Promise { 10 }
    */
    
    const p8 = Promise.resolve(10).finally(() => Promise.reject('error'))
    const p9 = Promise.resolve(10).finally(() => {throw 'error'})
    const p10 = Promise.resolve(10).finally(() => new Promise((resolve,reject) => {}))
    
    setTimeout(console.log, 0 , 'p8',p8) // p8 Promise { <rejected> 'error' }
    setTimeout(console.log, 0, 'p9',p9) // p9 Promise { <rejected> 'error' }
    setTimeout(console.log, 0, 'p10',p10) // p10 Promise { <pending> }
    
Promise静态方法
  • Promise.resolve

    • 将一个值变成一个 fulfilled 状态的实例

    • 有一个参数,可选

      • 参数是一个Promise实例:原封不动的返回,可以理解为浅拷贝
      const p = Promise.resolve(10)
      const f = Promise.reject('error')
      let fulfilled = Promise.resolve(p)
      console.log('fulfilled',fulfilled, fulfilled === p) // fulfilled Promise { 10 } true
      fulfilled=Promise.resolve(f)
      console.log('fulfilled',fulfilled, fulfilled === f) // fulfilled Promise { <rejected> 'error' } true
      
      • 参数是一个普通值:Promise.resolve将这个普通值包成一个 fulfilled 状态实例
      let p = Promise.resolve('10')
      console.log(p) // Promise { '10' }
       p = Promise.resolve(10)
      console.log(p)  // Promise { 10 }
      
      • 无参数:将 undefined 包成一个 fulfilled 状态实例
      console.log(Promise.resolve()) // Promise { undefined }
      
      
      • 参数是一个thenable对象:thenable是指具有 then方法的对象;将这个 thenable对象转换成Promise对象,并且会立即调用这个 then 方法,所以此时这个Promise对象的状态就由 then 方法说了算,先调用 resolve 那么就是 fulfilled 状态实例,先调用 reject 那么就是 fulfilled 状态实例,哪个都不调用就是 pending 状态实例
      let thenable = {
        then(resolve,reject) {
          console.log('这是 thenable的then方法')
          resolve('success')
        }
      }
      let p = Promise.resolve(thenable)
      setTimeout(console.log, 0, p)
      
      //
      这是 thenable的then方法
      Promise { 'success' }
      
  • Promise.reject

    • 将一个值变成一个 rejected 状态的实例

      • 参数是一个Promise实例:将这个 Promise 实例包裹成一个 rejected 状态实例
      const r = Promise.reject('error')
      const f = Promise.resolve('success')
      console.log(Promise.reject(r))
      console.log(Promise.reject(f))
      //
      Promise { <rejected> Promise { <rejected> 'error' } }
      Promise { <rejected> Promise { 'success' } }
      
      • 参数是一个普通值:Promise.reject将这个普通值包成一个 rejected 状态实例
      console.log(Promise.reject('10'))
      console.log(Promise.reject(10))
      //
      Promise { <rejected> '10' }
      Promise { <rejected> 10 }
      
      • 无参数:将 undefined 包成一个 rejected 状态实例
      console.log(Promise.reject())
      Promise { <rejected> undefined }
      
      • 参数是一个thenable对象,同 Promise.resolve
  • Promise.all

Promise.all将一组Promise实例(注意:Promise.all()方法接受一个数组作为参数,数组里面每一项都应该是 Promise实例,如果不是则会自动转换成 Promise实例,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。)包装成一个新的实例,待这一组Promise实例对象状态全部变成 fulfilled 状态,就会返回一个新的 fulfilled 状态实例,这个新的 fulfilled 状态实例存放了这一组Promise实例的结果;

let p1 = Promise.resolve(1)
let p2 = Promise.resolve(10)
let p3 = Promise.resolve(100)
let results = Promise.all([p1,p2,p3])
setTimeout(console.log,0, results)
//
Promise { [ 1, 10, 100 ] }

如果其中有任意一个 rejected 时立即结束,并返回这个 rejected 状态实例

适合彼此相互依赖或者在其中任何一个reject时立即结束。

p1 = Promise.reject('error')
 results = Promise.all([p1,p2,p3])
setTimeout(console.log,0, results)
//
Promise { <rejected> 'error' }

注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()catch方法,而是调用自己的 catch 方法

p1 = new Promise((resolve, reject) => {
  resolve('resolve')
}).then(res =>
    res
).catch(err => err)

p2 = new Promise((resolve, reject) => {
  reject('reject')
})
    .then(res => res)
    .catch(err => err)
result = Promise.all([p1, p2]).then(res => console.log('res-result', res)).catch(err => console.log('err-result', err))
//
res-result [ 'resolve', 'reject' ]

注意,由于p2调用来自己的 catch 方法,所以最后 p2也会变成 fulfilled 状态实例,所以Promise.all()方法参数里面的两个实例都会fulfilled,因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数。

  • Promise.race

将多个Promise实例包装成一个Promise实例,只要其中一个状态改变了(不论是rejected还是fulfilled),那么这个方法就会返回这个状态改变的Promise实例

const p1 = new Promise((resolve,reject) => {
  setTimeout(() => resolve('success'), 1000)
})
const p2 = new Promise((resolve,reject) => {
  setTimeout(() => reject('error'), 0)
})
const result = Promise.race([p1,p2])
setTimeout(console.log, 1500, 'result',result) // result Promise { <rejected> 'error' }

注意:如果Promise.race的参数是一个空数组,那么最后返回的结果是一个 pending 实例

const res = Promise.race([])
setTimeout(console.log, 0, 'res',res) // res Promise { <pending> }
  • Promise.allSettled

Promise.allSettled()方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。

当有多个彼此不依赖的异步任务成功完成时,或者总是想知道每个promise的结果时,通常使用它。

const p1 = Promise.resolve('resolve')
const p2 = Promise.resolve('reject')

let result = Promise.allSettled([p1,p2])
setTimeout(console.log, 0, result)
//
Promise {
  [
    { status: 'fulfilled', value: 'resolve' },
    { status: 'fulfilled', value: 'reject' }
  ]
}

这个方法就返回一个新的Promise实例,并且这个实例附带了这一组Promise实例的结果,并带有一个对象数组,每个对象表示对应的promise结果。

  • Promise.any(待补充)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值