一、先给面试官一个结论版

如果面试官问 "你怎么理解 Promise?" ,不要上来就背 API。
更好的开场是先说本质:

Promise 是 ES6 引入的一种用于处理异步操作的解决方案。
它的核心价值是:把异步操作的最终结果(成功或失败)用一种统一的方式表达出来,避免了传统回调函数嵌套带来的"回调地狱"问题,让异步代码可以写得像同步一样清晰。

这段开场就很有力度。


二、为什么需要 Promise?

要理解 Promise,先要理解它解决了什么问题。


回调地狱

ES6 之前,异步操作主要依赖回调函数:

ajax('/api/user', function(user) {
  ajax('/api/orders?id=' + user.id, function(orders) {
    ajax('/api/detail?id=' + orders[0].id, function(detail) {
      // 终于拿到数据...
    })
  })
})

这种写法有几个问题:

  • 嵌套层次深,可读性差
  • 错误处理复杂,每一层都要单独处理
  • 逻辑难以维护和复用

Promise 就是为了解决这些问题而生的。


三、Promise 是什么?


1)本质

Promise 是一个对象,代表一个 异步操作的最终完成或失败

它有三种状态:

状态 说明
pending 进行中,初始状态
fulfilled 已成功,操作完成
rejected 已失败,操作出错

状态特点

  • 状态只能由 pending 变成 fulfilled,或 pending 变成 rejected
  • 一旦状态确定,就不会再改变

这个不变性非常重要,面试一定要说。


2)基本用法

const promise = new Promise((resolve, reject) => {
  // 异步操作
  setTimeout(() => {
    const success = true
    if (success) {
      resolve('操作成功')
    } else {
      reject('操作失败')
    }
  }, 1000)
})

promise
  .then(result => {
    console.log(result) // 操作成功
  })
  .catch(err => {
    console.log(err) // 操作失败
  })

3)关键方法

.then()

接收成功的结果,返回一个新的 Promise。

promise.then(value => {
  console.log(value)
})

.catch()

接收失败的结果,相当于 .then(null, onRejected)

promise.catch(err => {
  console.log(err)
})

.finally()

无论成功还是失败都会执行(ES2018,但常和 Promise 一起考)。

promise.finally(() => {
  console.log('结束了')
})

四、Promise 的链式调用

这是 Promise 解决"回调地狱"的核心机制。

每次 .then() 都会返回一个新的 Promise,所以可以链式调用:

ajax('/api/user')
  .then(user => ajax('/api/orders?id=' + user.id))
  .then(orders => ajax('/api/detail?id=' + orders[0].id))
  .then(detail => {
    console.log(detail)
  })
  .catch(err => {
    console.log(err)
  })

和回调地狱相比,代码更扁平、更清晰。

面试加分说法

链式调用的核心是 .then() 每次都返回一个新的 Promise,而不是原来的那个。
这就让异步操作可以像同步一样"排队"执行。


五、Promise 的静态方法

这部分非常高频,面试必问。


1)Promise.all()

作用

等待所有 Promise 都成功,才算成功;只要一个失败,就失败。

Promise.all([
  fetch('/api/a'),
  fetch('/api/b'),
  fetch('/api/c')
]).then(([a, b, c]) => {
  console.log(a, b, c)
}).catch(err => {
  console.log(err)
})

适用场景

  • 多个请求同时发出,等全部完成再处理
  • 并行请求,且结果全部需要

面试加分点

Promise.all() 是并行执行,不是串行。结果数组的顺序和传入的 Promise 顺序一致,和谁先完成无关。


2)Promise.race()

作用

多个 Promise 中,谁最先改变状态就以谁为准。

Promise.race([
  fetch('/api/a'),
  new Promise((_, reject) => setTimeout(reject, 3000, '超时'))
]).then(result => {
  console.log(result)
}).catch(err => {
  console.log(err) // 超时
})

适用场景

  • 超时控制
  • 竞速场景

3)Promise.allSettled()

作用

等所有 Promise 都完成(不管成功还是失败),返回每个 Promise 的结果。

Promise.allSettled([
  Promise.resolve(1),
  Promise.reject('error'),
  Promise.resolve(3)
]).then(results => {
  results.forEach(result => {
    console.log(result)
  })
})
// { status: 'fulfilled', value: 1 }
// { status: 'rejected', reason: 'error' }
// { status: 'fulfilled', value: 3 }

与 Promise.all() 的区别

  • Promise.all():有一个失败就结束
  • Promise.allSettled():等全部结束,不管成不成功

适用场景

  • 批量请求,希望知道每一个的结果,不管成败
  • 上报场景,不能因为某个接口失败就漏掉其他的

4)Promise.any()

作用

只要有一个 Promise 成功,就成功;所有都失败,才失败。

Promise.any([
  Promise.reject('err1'),
  Promise.resolve('ok'),
  Promise.reject('err2')
]).then(result => {
  console.log(result) // ok
})

和 Promise.race() 的区别

  • Promise.race():最快的那个,不管成功还是失败
  • Promise.any():最快成功的那个

5)Promise.resolve() / Promise.reject()

快速创建一个已经成功或失败的 Promise:

Promise.resolve(1).then(v => console.log(v)) // 1
Promise.reject('err').catch(e => console.log(e)) // err

六、Promise 的使用场景

这部分是面试里很想听到的,要结合实际说。


1)接口请求封装

function request(url) {
  return new Promise((resolve, reject) => {
    fetch(url)
      .then(res => res.json())
      .then(data => resolve(data))
      .catch(err => reject(err))
  })
}

2)多个请求并行

Promise.all([
  request('/api/user'),
  request('/api/config')
]).then(([user, config]) => {
  // 全部拿到再处理
})

3)超时控制

function timeout(promise, ms) {
  const timer = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('请求超时')), ms)
  )
  return Promise.race([promise, timer])
}

4)串行执行异步任务

const tasks = [taskA, taskB, taskC]

tasks.reduce((prev, task) => {
  return prev.then(() => task())
}, Promise.resolve())

5)Loading 状态管理

setLoading(true)

request('/api/data')
  .then(data => {
    renderData(data)
  })
  .catch(err => {
    showError(err)
  })
  .finally(() => {
    setLoading(false)
  })

6)懒加载 / 图片预加载

function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.onerror = reject
    img.src = src
  })
}

七、Promise 的缺点

主动说出缺点,会让面试官觉得你很成熟。


1)无法取消

Promise 一旦创建就会执行,无法中途取消。
这是它比较明显的局限。


2)内部错误不会抛出到外层

如果没有 .catch(),内部的错误可能被静默吞掉:

const p = new Promise(() => {
  throw new Error('出错了')
})
// 没有 .catch(),这个错误不会抛到外部

3)无法监测当前进度

Promise 只有三种状态,无法知道当前处于"第几步"。


八、Promise 和 async/await 的关系

这是面试里最常被追问的内容,要准备好。

async/await 是 Promise 的语法糖,它并没有取代 Promise,而是让 Promise 的使用方式更直观。
async 函数的返回值是一个 Promise,await 的本质是在 .then() 上的等待。

// Promise 写法
request('/api/data')
  .then(data => console.log(data))
  .catch(err => console.log(err))

// async/await 写法
async function getData() {
  try {
    const data = await request('/api/data')
    console.log(data)
  } catch (err) {
    console.log(err)
  }
}

面试加分说法

我通常优先用 async/await,因为它更贴近同步写法,可读性更好。
但在需要并行执行的场景,还是会配合 Promise.all() 使用,不能全部改成串行 await,否则会损失并发性能。

这句非常加分。


九、面试标准回答

我理解 Promise 是 ES6 引入的用于处理异步操作的解决方案。
它的本质是一个对象,代表一个异步操作的最终结果,有三种状态:pendingfulfilledrejected,而且状态一旦确定就不可逆。

它的核心价值在于解决了回调地狱的问题。传统回调嵌套深、错误处理难,而 Promise 通过链式调用,让异步代码可以写得更扁平、更清晰。

从方法上看,常用的有 .then().catch().finally(),以及静态方法 Promise.all()Promise.race()Promise.allSettled()Promise.any()
其中 Promise.all() 适合并行请求全部完成的场景;Promise.race() 适合超时控制;Promise.allSettled() 适合需要知道每个请求结果的批量场景。

实际开发中,Promise 常用于接口请求封装、多接口并行、超时控制、Loading 状态管理、图片预加载等场景。

另外,async/await 是 Promise 的语法糖,它让代码更像同步写法,可读性更好。我通常优先用 async/await,但在并行场景里还是会配合 Promise.all() 使用,避免把并行请求变成串行,损失性能。

当然 Promise 也有缺点,比如无法取消、无法获取中间进度、没有 .catch() 的话内部错误容易被吞掉,这些在使用时需要注意。


十、精简版面试回答

如果时间比较短,可以这样答:

Promise 是 ES6 用于处理异步的解决方案,核心是用一个对象表示异步操作的最终结果,状态有 pendingfulfilledrejected,且状态一旦确定不可改变。
它解决了回调地狱的问题,通过链式 .then() 让异步代码更清晰。
常用方法有 .then().catch(),静态方法有 Promise.all()Promise.race()Promise.allSettled() 等,分别适用于并行等待、竞速、批量结果收集等场景。
实际上我更多是配合 async/await 使用,让代码更接近同步写法,但并行场景还是会用 Promise.all() 保持并发性能。


十一、一句话总结

面试官真正想听的是:

  • 你是否理解 Promise 解决了什么问题
  • 你能不能说清楚 三种状态和不可逆性
  • 你是否熟悉 常用方法和静态方法
  • 你能不能结合 实际场景 来说使用价值
  • 你有没有意识到 async/await 和 Promise 的关系
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐