Skip to content

to

将 Promise 的结果转换为一个 [error, data] 元组,以便在 async/await 中进行无 try/catch 的优雅错误处理。

示例

基本用法

当 Promise 成功时,返回 [null, data]

typescript
async function fetchUser() {
  const promise = Promise.resolve({ id: 1, name: 'Alice' })
  const [error, user] = await to(promise)

  if (error) {
    // 这段代码不会执行
    return
  }

  return user
}

const user = await fetchUser()
// => { id: 1, name: 'Alice' }

处理错误

当 Promise 失败时,返回 [error, undefined]

typescript
async function fetchWithError() {
  // eslint-disable-next-line prefer-promise-reject-errors
  const promise = Promise.reject('Network Error')
  const [error, data] = await to(promise)

  if (error) {
    console.error(error) // => 'Network Error'
    return null
  }

  // 这段代码不会执行
  return data
}

await fetchWithError()
// => null

附加错误信息

在捕获错误时,可以附加额外的上下文信息到错误对象上。

typescript
async function fetchWithContext() {
  // eslint-disable-next-line prefer-promise-reject-errors
  const promise = Promise.reject({ code: 404, message: 'Not Found' })
  const [error, data] = await to(promise, { requestId: 'xyz-123' })

  return error
}

const error = await fetchWithContext()
// => { code: 404, message: 'Not Found', requestId: 'xyz-123' }

签名与说明

typescript
/**
 * 将 Promise 转换为一个元组,包含错误和数据。
 * 这种模式源于 Go 语言的错误处理方式,允许在不使用 try-catch 块的情况下处理 async/await 操作的可能失败。
 *
 * @template T 成功解决时数据的类型。
 * @template U 失败时错误的类型,默认为 Error。
 * @param {Promise<T>} promise 要处理的 Promise 实例。
 * @param {object} [errorExt] 当 Promise 失败时,要附加到错误对象上的额外属性。
 * @returns {Promise<[U, undefined] | [null, T]>}
 *          一个总是会成功解决的 Promise。
 *          - 如果输入的 Promise 成功,它会解决为 `[null, T]`。
 *          - 如果输入的 Promise 失败,它会解决为 `[U, undefined]`。
 */
export function to<T, U = Error>(
  promise: Promise<T>,
  errorExt?: object,
): Promise<[U, undefined] | [null, T]>

注意事项与边界情况

  • 总是解决: to 函数本身返回的 Promise 总是会解决 (resolve),绝不会拒绝 (reject)。它将输入 Promise 的拒绝状态转化为元组中的一个值。
  • 成功情况: 当输入的 Promise 成功解决时,返回的元组第一项为 null,第二项为 Promise 的解决值。
  • 失败情况: 当输入的 Promise 被拒绝时,返回的元组第一项为拒绝的原因(错误对象),第二项为 undefined
  • 错误扩展: 提供的 errorExt 对象仅在输入 Promise 被拒绝时生效,它的属性会被合并到最终的错误对象中。如果 Promise 成功,errorExt 将被忽略。

相关链接

基于 MIT 许可证发布