Skip to content

Promise

Promise 的意义 - Promise 是异步编程的一种解决方案,是一个对象,通过它可以获取异步操作的消息

Promise 对象有以下特点

  1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 Promise 这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

  2. 一旦状态改变,就不会再次改变 (Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。)

  3. 任何时候都可以得到结果

缺点

  1. 无法取消 Promise

一旦新建它就会立即执行,无法中途取消。

js
const promise = new Promise(function (resolve, reject) {
  // 这边会立即执行,而不像回调函数  这是一个函数 需要调用一下,当然也可以变成自执行函数
  if (true) {
    resolve(value)
  } else {
    reject(error)
  }
})
  1. 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。
js
try {
  const promise = new Promise(function (resolve, reject) {
    // 这边会立即执行,而不像回调函数  这是一个函数 需要调用一下,当然也可以变成自执行函数
    throw new Error("这是错误")
  }).catch(error => {
    console.log(`promise catch error : `, error)
  })
} catch (error) {
  console.log(`外部捕获`, error) //不会执行,只能通过 promise.catch()
}

外部错误

  1. 当处于 pending 状态时,无法得知目前进展到哪一个阶段

这就是所这有三种状态 没有中间的状态了

什么是回调地狱? Promise 如何解决回调地狱?

回调地狱 - 如果我们在回调内部存在另外一个异步操作,即出现多层嵌套问题,导致变成一段混乱且不可读的代码,此代码就称为'回调地狱'

多层嵌套问题 每种任务的处理结果存在两种可能性(成功或失败),那么需要在每种任务执行结束后分别处理这两种可能性

这两个问题在回调函数中尤为突出,Promise 的诞生就是为了解决这两个问题

Promise 解决'回调地狱'

  • 回调函数延迟绑定
js
const promise1 = new Promise(function (resolve, reject) {
  // 这边会立即执行,而不像回调函数  这是一个函数 需要调用一下,当然也可以变成自执行函数
  throw new Error("这是错误")
  // 延迟绑定回调函数
})
  .then(res => {
    return Promise.reject(`内部第二个promise的error`)
  })
  .catch(err => {
    console.log(`promise catch error : `, err)
  })
  • 返回值穿透
js
const promise1 = new Promise(function (resolve, reject) {
  // 这边会立即执行,而不像回调函数  这是一个函数 需要调用一下,当然也可以变成自执行函数
  resolve(1)
  // 延迟绑定回调函数
})
  .then(res => {
    console.log(res)
    return Promise.resolve(`内部第二个promise`)
  })
  .then(res => {
    console.log(res)
    return Promise.reject(`内部第二个promise err`)
  })
  .catch(err => {
    console.log(`promise catch error : `, err)
  })

外部错误

  • 错误冒泡

Promise.then()

  1. then 方法返回的是一个新的 Promise 实例(注意,不是原来那个 Promise 实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。
js
const promise1 = new Promise(function (resolve, reject) {
  // 这边会立即执行,而不像回调函数  这是一个函数 需要调用一下,当然也可以变成自执行函数
  resolve(1)
  // 延迟绑定回调函数
})
  .then(res => {
    console.log(res)
    return Promise.resolve(`内部第二个promise`)
  })
  .then(res => {
    console.log(res)
    return Promise.reject(`内部第二个promise err`)
  })
  .catch(err => {
    console.log(`promise catch error : `, err)
  })

Promise 主体中返回一个 字符串是不会向下执行的

  • 如果 then 中的回调函数又返回(return),那么 then 返回的 Promise 就会变成接受状态(resolved),并且将返回的值作为接受状态的回调函数的参数值

  • 如果 then 中的回调函数抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态(rejected),并且将抛出的错误作为拒绝状态的回调函数的参数值(后面的 then 也不会再执行)

  • 如果 then 中的回调函数返回一个**未定状态(pending)**的 Promise,那么 then 返回的 Promise 也是未定状态,并且它的最终状态会与那个 Promise 的最终状态相同,同时,它变为终态时调用的回调函数的参数值与那个 Promise 变为终态时的回调函数的参数值相同

js
new Promise(function (resolve, reject) {
  return "字符串的值"
})
  .then(res => {
    console.log(res) //不会执行
  })
  .catch(error => {
    console.log(`promise catch error : `, error)
  })

new Promise(function (resolve, reject) {
  resolve(1)
})
  .then(res => {
    console.log(res) // 1
    return "这是then返回的,而不是primise中返回的"
  })
  .then(res => {
    console.log(res) // 这是then返回的,而不是primise中返回的
    return
  })
  .then(res => {
    console.log(res) // 打印的是undefined
    return new Promise(function (resolve, reject) {
      setTimeout(() => {
        resolve("3s resolve")
      }, 3000)
    })
  })
  .then(res => {
    console.log(res) // 3s 才会打印 '3s resolve'
    throw new Error(`这是then中的错误`)
  })
  .then(res => {
    console.log("还会执行么?") // 不会再执行了
  })
  .catch(error => {
    console.log(`promise catch error : `, error)
  })

题目

  1. 题 1
js
const log = s => {
  console.log(s)
}
log(1)

new Promise(resolve => {
  resolve(2)
}).then(v => {
  log(v)
})

async function fn1() {
  log(3)
}

async function fn2() {
  log(4)
  await fn1()
  log(5)
}

fn2()

结果为: 14325

Promise.all

Promise.all(iterable)   方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。

全部正常

js
const promise1 = Promise.resolve(1)
const promise2 = 2
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3)
})

Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values)
})
// 结果为 : Array [1, 2, 3]

第一个失败的原因

js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject(2)
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3)
})

Promise.all([promise1, promise2, promise3]).then(err => {
  console.log(values)
})
// 结果为 : 2

Promise.allSettled

Promise.allsettled(iterable) 方法方法返回一个在所有给定的 promise 已被决议或被拒绝后决议的 promise,并带有一个对象数组,每个对象表示对应的 promise 结果

全部正常

js
const promise1 = Promise.resolve(1)
const promise2 = 2
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3)
})

Promise.allsettled([promise1, promise2, promise3]).then(values => {
  console.log(values)
})
// 结果为 : Array [1, 2, 3]

有失败也会全部返回

js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3)
})

Promise.allsettled([promise1, promise2, promise3]).then(err => {
  console.log(values)
})
// 结果为 : [1,"err 2",3]

Promise.any()

Promise.any() 静态方法将一个 Promise 可迭代对象作为输入,并返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。

只要有一个正常,就返回第一个正常的结果

js
const promise1 = Promise.resolve(1)
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 3)
})

Promise.allsettled([promise1, promise2, promise3]).then(values => {
  console.log(values)
})
// 结果为 : 1

全部失败才会返回所有的失败原因

js
const promise2 = Promise.reject("err 2")
const promise3 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, "err 3")
})

Promise.allsettled([promise2, promise3]).then(err => {
  console.log(values)
})
// 结果为 : ["err 2","err 3"]

Promise.race()

返回第一个 履行或拒绝 的结果