js - promise

promise 是什么

  • 抽象表达:Promise 是JS中进行异步变成的新的解决方案
  • 具体表达:
    • 从语法上来说:Promise 是一个构造函数
    • 从功能上来说:promise 对象用来封装一个异步操作并可以获取其结果

promise与传统的回调对比

  1. 传统回调模式是回调地狱写法,非常不便于书写及阅读,使代码更臃肿,而 promise 支持链式调用,代码可以从上往下发展
  2. 配合使用 asyncawait 会让异步代码变为同步代码
  3. 传统回调模式指定回调时,只能是在任务启动前,而 promise 可以在任务启动后才指定回调,例如可以在等多长时间后才指定回调处理
  4. promise 可以对同一个任务指定多个回调

promise的一些关键问题

1. 如何改变promise的状态?
  • resolve(value) :如果当前状态是 pending 就会变成 resolved
  • reject(reason) :如果当前状态是 pending 就会变成 rejected
  • 抛出异常 throw new Error('reason'):如果当前状态是 pending 就会变成 rejected
2. 对一个 promise 指定多个成功/失败的回调,是否都会执行

答:当 promise 的状态改变后,都会执行对应成功/失败的多个回调

const p = new Promise((resolve, reject) => {
  resolve()
})
p.then(res => {})
p.then(res => {})
p.then(res => {})
// ...
3. 改变 promise 状态和指定回调函数谁先谁后
  • 都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调
  • 如何先改变状态在指定回调?
    1. 在执行器中调用 resolve()reject 改变状态
    2. 延迟更长时间再调用 then()
 const p = new Promise((resolve, reject) => {
   resolve()
 })
 setTimeout(() => {
   p.then(value => {})
 }, 5000)
4. promise.then() 返回的新 promise 的结果状态由什么决定
  • 简单表达:由 then() 指定的回调函数执行的结果决定
  • 详细表达
    • 如果抛出异常:新 promise 的状态变为 rejectedreason 为抛出的异常
    • 如果返回的是非 promise 的任意值,新 promise 的状态变为 resolvedvalue 为返回的值,什么都不返回的情况,函数会返回 undefinedundefined 也是非 promise 的值
    • 如果返回的是一个新的 promise ,此 promise 的结果就会成为新 promise 的结果
5. 回调函数是同步还是异步执行

答:promise 的回调函数属于异步任务,会在同步任务之后执行。但不是正常的异步任务,而是 微任务(microtask)

JS宏队列与微队列说明

 // 定时器回调是 宏任务
 setTimeout(() => {
   console.log('定时器回调')
 })

 // promise回调是 微任务
 new Promise((resolve, reject) => {
   resolve()
 }).then(res => {
   console.log('promise回调')
 })

 // 执行结果如下:微任务会比宏任务先执行
 // promise回调
 // 定时器回调
6. promise 异常传透?

当使用 promise 的链式调用时(p.then().then() ...),可以在最后指定失败的回调(.catch(() => {})),因为前面任何操作出现了异常,都会传到最后失败的回调中处理

// 第一层把 promise 的状态改为 rejected 失败状态后,下一层如果没写失败回调,则继续抛出异常,就这样一层一层的往下传
new Promise((resolve, reject) => {
  reject('错误')
}).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).catch(reason => {
  console.log(reason)
})
7. 如何终端 promise 链?

在回调函数中返回一个 pending 状态的 promise 对象

new Promise((resolve, reject) => {
  reject('错误')
}).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).then(
  value => 'ok',
  // 不写失败回调,内部会默认这样的写法
  reason => {throw reason}
).catch(reason => {
  // 到了这一步后,如果后面还有回调,但是需要再这里终止 promise 链,

  // × 返回 失败的 promise 后还是会进入到下一个失败的回调
  // return Promise.reject('失败')

  // × 抛出异常后还是会进入到下一个失败的回调
  // throw '失败'

  // √ 返回一个 pending 状态的 promise
  return new Promise(() => {})
}).then(
  value => {
    console.log('成功回调')
  },
  reason => {
    console.log('失败回调')
  }
)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值