# 一、其他 Promise 方法

  除了上面介绍的常见的 Promise 原型对象上的方法,和 Promise 函数对象部分方法外。还有其他的方法需要我们了解一下。

  在实际开发中,Promise 常用在处理异步请求中。如果只是一个请求还好,如果同时在 Promise 中处理多个异步请求呢?

# 1、Promise.all

  Promise.all()可以将多个 Promise 实例包装成一个新的 Promise 实例

const p = Promise.all([p1, p2, p3])

// p1 && p2 && p3

  p1、p2、p3 都为 fulfilled 状态时,p 的状态才会变为 fulfilled。

  只要 p1、p2、p3 其中的任何一个变为 rejected 状态时,p 的状态就会变为 rejected。

应用:处理多个类似的异步请求
  • 常规方式
var list = [1, 3, 5]

list.forEach((item) => {
  $.ajax(`https://jsonplaceholder.typicode.com/posts/${item}`).then((res) => {
    console.log(res) // 分为三次打印 {…}
  })
})
  • Promise.all 方式
var list = [1, 3, 5]

function getData(list) {
  var newlist = list.map((item) => $.ajax(`https://jsonplaceholder.typicode.com/posts/${item}`))

  return Promise.all(newlist) // 🎈
}

getData(list)
  .then((res) => {
    console.log(res) //  [{…}, {…}, {…}]
  })
  .catch((err) => {
    console.log(err)
  })

# 2、Promise.race

  Promise.race()可以将多个 Promise 实例包装成一个新的 Promise 实例

const p = Promise.race([p1, p2, p3])

// p1 || p2 || p3

  与前面的 Promise.all 不同的是,只要 p1、p2、p3 其中的任何一个状态发生变化,p 的状态就会跟着变化

应用 1:差异比较
var p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('data1')
  }, 1000)
})

var p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('data2')
  }, 2000)
})

Promise.race([p1, p2]).then((res) => {
  console.log(res) // data1
})
应用 2:请求超时检测
var p1 = $.ajax('https://jsonplaceholder.typicode.com/comments?postId=1')

var p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('请求超时')
  }, 4000)
})

Promise.race([p1, p2])
  .then((res) => {
    console.log(res) // {…}
  })
  .catch((err) => {
    console.log(err)
  })
应用 3:多节点服务器请求
var p1 = ajax('https://jsonplaceholder.typicode.com/posts/1')
var p2 = ajax('https://jsonplaceholder.typicode.com/posts/2')
var p3 = ajax('https://jsonplaceholder.typicode.com/posts/3')
var p4 = ajax('https://jsonplaceholder.typicode.com/posts/4')

Promise.race([p1, p2, p3, p4])
  .then((res) => {
    console.log(res) // {…}
  })
  .catch((err) => {
    console.log(err)
  })

# 3、Promise.allSettled

  在前面的 Promise.all 方法中,我们发现:

只要 p1、p2、p3 其中的任何一个变为 rejected 状态时,p 的状态就会变为 rejected。

  但这会导致一个问题,成功的数据会因为某个接口发生错误而无法得到数据。

  ES2020 即 ES11 发布的 Promise.allSettled 方法就可以解决上述问题。

const p = [ajax('/200接口'), ajax('/401接口')]

Promise.allSettled(promises)
  .then((res) => {
    {
      // 成功的请求响应数据
      const successList = res.filter((item) => item.status === 'fulfilled')

      // 失败的请求响应数据
      const errorList = res.filter((item) => item.status === 'rejected')
    }
  })
  .catch((err) => {
    console.log(err)
  })

# 4、Promise.any

  Promise.any()可以将多个 Promise 实例包装成一个新的 Promise 实例

const p = Promise.any([p1, p2, p3])

  只要 p1、p2、p3 其中的任何一个变为 fulfilled 状态时,p 的状态就会变为 fulfilled。

  p1、p2、p3 都为 rejected 状态时,p 的状态才会变为 rejected。

通过比较 Promise.all 的状态变化关系和 Promise.any 的转态变化关系恰恰相反

  • 会员联盟系统
const p1 = new Promise((resolve, reject) => {
  // 沃尔玛的登录逻辑
})
const p2 = new Promise((resolve, reject) => {
  // 华润的登录逻辑
})
const p3 = new Promise((resolve, reject) => {
  // 盒马的登录逻辑
})

Promise.any([p1, p2, p3])
  .then((res) => {
    console.log(res)
    // 跳转到主页
  })
  .catch((err) => {
    console.log(err)
    // 请注册
  })

# 二、执行顺序问题 ✍

提示

  • Promise 的 excutor 函数是 同步回调
  • Promise 的.then / .catch 中的 成功|失败函数 是异步回调

# 1、问题 1

是先 promise 改变状态,还是先指定回调函数?

  • 常规
new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('--- one ---')
    // 后改变状态(异步执行回调函数)
    resolve(1)
  })
}).then(
  // 先指定回调函数
  (res) => {
    console.log('--- two ---')
  },
  (err) => {}
)

console.log('--- -- ---')
  • 也可以
new Promise((resolve, reject) => {
  console.log('--- one ---')
  // 先改变状态
  resolve(1)
}).then(
  // 后指定回调函数(异步执行回调函数)
  (res) => {
    console.log('--- two ---')
  },
  (err) => {}
)

console.log('--- -- ---')

# 2、问题 2

promise.then() 返回的新 promise 的结果状态由什么决定?

new Promise((resolve, reject) => {
  resolve(1)
  // reject(1)
})
  .then(
    (res) => {
      console.log('onFulfillment-1', res)

      // return undefined  // 默认
      // return 2
      // return Promise.resolve(3)
      // throw 4
    },
    (err) => {
      console.log('onRejection-1', err)
    }
  )
  .then(
    (res) => {
      console.log('onFulfillment-2', res)
    },
    (err) => {
      console.log('onRejection-2', err)
    }
  )

结果:

onFulfillment-1 1
onFulfillment-1 undefined

// 或者

onRejection-1 1
onFulfillment-1 undefined

# 3、问题 3

Promise.then()的链式调用中,同步/异步任务执行顺序是怎样的?

new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('开始执行:异步任务 1')
    resolve(1)
  })
})
  .then((res) => {
    console.log('任务1的结果:', res)

    console.log('开始执行:同步任务 2')
    return 2
  })
  .then((res) => {
    console.log('任务2的结果:', res)

    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('开始执行:异步任务 3')
        resolve(3)
      })
    })
  })
  .then((res) => {
    console.log('任务3的结果:', res)
  })

console.log('--- -- ---')

# 4、问题 4

什么是 Promise 异常传透?怎样中断 Promise 链?

new Promise((resolve, reject) => {
  reject(1)
})
  .then(
    (res) => {}
    // (err) => {throw reason}  // 默认操作
  )
  .then(
    (res) => {}
    // (err) => {throw reason}  // 默认操作
  )
  .catch((err) => {
    console.log(err)
  })
new Promise((resolve, reject) => {
  reject(1)
})
  .then(
    (res) => {},
    (err) => {
      console.log('onRejection-1', err)

      // 中断promise链
      return new Promise(() => {})
    }
  )
  .then(
    (res) => {
      console.log('onFulfillment-1', res)
    },
    (err) => {
      console.log('onRejection-1', err)
    }
  )
更新于 : 7/8/2024, 10:21:14 AM