Skip to content

to

将任意 Promise 的结果转换为 [error, data] 元组,方便在 async/await 流程中以更加直观的方式处理成功与失败。

示例

基本用法:处理成功结果

typescript
import { to } from '@esdora/kit'

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

  if (error) {
    return null
  }

  return user
}

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

捕获错误而不抛出异常

typescript
import { to } from '@esdora/kit'

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
import { to } from '@esdora/kit'

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

  return error
}

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

签名与说明

类型签名

typescript
export function to<T, U = Error>(
  promise: Promise<T>,
  errorExt?: object,
): Promise<[U, undefined] | [null, T]>

参数说明

参数类型描述必需
promisePromise<T>需要被包装的 Promise,T 为其成功结果的类型
errorExtobject | undefined可选的扩展信息对象,当 Promise 被拒绝时会合并到错误对象上

返回值

  • 类型: Promise<[U, undefined] | [null, T]>
  • 说明:
    • 返回一个永远不会 reject 的 Promise
    • 当输入 Promise 成功时,解析为 [null, data]
    • 当输入 Promise 失败时,解析为 [error, undefined]
  • 特殊情况:
    • 当传入 errorExt 且 Promise 被拒绝时,最终的错误值为 Object.assign({}, err, errorExt)
    • 如果错误值本身不是对象(例如字符串),扩展属性会按 JavaScript 的对象合并规则尝试添加

泛型约束(如适用)

  • T: 表示 Promise 成功解析时的数据类型,例如 numberUser 等。
  • U: 表示错误类型,默认是 Error;当你在项目中使用自定义错误类型时,可以显式指定。

注意事项与边界情况

输入边界

  • promise 参数应为一个合法的 Promise 实例;传入其它值会在运行时导致类型错误。
  • 不支持传入非 Promise 值(例如普通对象或函数),这类使用方式会违背 TypeScript 类型签名。
  • errorExt 建议为普通对象,便于通过 Object.assign 正确合并属性。

错误处理

  • to 自身不会抛出异常,而是将错误封装在返回的元组中:
    • 成功:[null, data]
    • 失败:[error, undefined]
  • 推荐在业务代码中始终检查元组的第一个元素来判断是否出错,而不是依赖 try...catch
  • 当你需要增加请求上下文信息(如 requestIdtraceId、接口名称等)时,可以通过 errorExt 提供,以便在日志或监控中追踪。

性能考虑

  • 时间复杂度: O(1),仅在原有 Promise 上追加一次 then/catch 链。
  • 空间复杂度: O(1),只创建一个包含两个元素的元组和极少量中间变量。
  • 优化建议:
    • 在性能敏感的热路径中,to 的开销可以认为与手写 try...catch 接近。
    • 更适合作为统一错误处理风格的工具,而不是解决极端性能问题的手段。

相关链接

基于 MIT 许可证发布