面试官:白话讲解Promise和then

151 阅读2分钟

Promise和then

定义

Promise是一个对象,用来返回一个异步函数的处理结果,可以让我们以同步编程的方式来进行异步操作,从而避免层层嵌套的回调地狱出现。

Promise的返回机制

那么Promise是如何实现的呐?Promise对象对三种状态,等待状态、成功状态以及失败状态。这三种状态是由Promise对象内的回调函数来决定的:

  • 当回调没有进行返回的时候,Promise处理等待状态(成功还是失败都不确定,因为没有返回)。
  • 当回调执行成功,Promise处于成功状态,并通过resolve()方法将执行的结果传递出去(我们可以在.then的回调函数中获取这个返回的结果)
  • 当回调执行失败,Promise处于失败状态,通过reject将错误传递出去

then的返回机制

那么Promise+then是如何避免回调地狱的呐?这就要来说说then的原理。当Promise成功执行之后,异步操作(Promise的回调)的结果通过resolve()被传入到then的回调函数中。在then的回调中:

  • 如果没有返回值,就默认是返回一个Promise对象;
  • 如果有返回值,但不是Promise对象,则默认通过Promise.resolve()的方法将其返回;
  • 如果返回的就是一个Promise对象,则将这个Promise对象返回。

解决回调地狱

正是由于then的返回机制,使得then()方法可以链式编程使用,并且后面的then以前面输出的结果为输入,从而使得我们可以用同步编程的方式来进行异步操作,从而用避免层层嵌套的回调地狱的出现。

Promise的静态方法

除此之外,Promise还有一些静态方法,例如:Promise.all()、Promise.allSettled()以及Promise.race()等。

Promise.all()

Promise.all()可以以数组的形式传入多个Promise对象,并将多个异步操作的结果进行返回,但是只要有一个异步操作调用了reject,该方法就是停止并且进入catch。

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 0)
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(2)
  }, 0)
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3)
  }, 0)
})

Promise.all([p1, p2, p3]).then(res => {
  console.log(res)
})

Promise.allSettled()

Promise.allSettled()与Promise.all()类似,区别是,then 始终可以获取到异步的状态,哪怕其中有一个失败。

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1)
  }, 0)
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(2)
  }, 0)
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3)
  }, 0)
})

Promise.allSettled([p1, p2, p3]).then(res => {
  console.log(res)
})

Promise.race()

Promise.race()使用和 all 一样,但是只返回第一个结果,不管成功或失败。

const p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(1)
  }, 500)
})

const p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(2)
  }, 200)
})

const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(3)
  }, 300)
})

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