Skip to content
0

错误处理

了解在 JS 中错误的处理

抛出的错误基本信息

我们使用 JSON.parse 来制造一个错误

try {
  JSON.parse('')
}
catch (e) {
  console.log(e)
}

执行后有如下输出:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at file:///path/to/project/src/error.js:13:8
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

如果我们希望得到 e 的内容,需要去读取 e.stack 而非 e 本身。这是因为 console.log 会对 e 进行处理,实际打印的就是 e.stack

catch (e) {
  fs.writeFileSync('./error.log', e.stack)
}

除此之外,e 对象还有另外两个属性 e.namee.message。分别是错误的名称和错误的描述。可以看出 e.stack 是包含这两部分的:

catch (e) {
  console.log('name:', e.name) //=> name: SyntaxError
  console.log('message:', e.message) //=> message: Unexpected end of JSON input
}

cause

es2020 扩展了 Error 对象的属性,允许在抛出错误的时候,额外传入一个 cause 参数,它可以是任何类型

cause 的出现,可以让 e.message 完全承载的自定义错误的类型,而相关更具体的错误原因叫由 cause 携带

它可以是一个携带业务上下文的对象

function makeRSA(p, q) {
  if (!Number.isInteger(p) || !Number.isInteger(q)) {
    throw new Error("RSA key generation requires integer inputs.", {
      cause: { code: "NonInteger", values: [p, q] },
    });
  }
  if (!areCoprime(p, q)) {
    throw new Error("RSA key generation requires two co-prime integers.", {
      cause: { code: "NonCoprime", values: [p, q] },
    });
  }
  // rsa algorithm…
}

也可以携带来自更深层的错误原因,这方便我们追踪、定位相关代码:

function doFailSomeWay() {
  throw new Error('TYPE_A_ERROR', { cause: 'doFailSomeWay' })
}
function doFailAnotherWay() {
  throw new Error('TYPE_B_ERROR', { cause: 'doFailAnotherWay' })
}

function doWork() {
  try { doFailSomeWay() } catch (err) {
    throw new Error('TYPE_C_ERROR', { cause: err })
  }
  try { doFailAnotherWay() } catch (err) {
    throw new Error('TYPE_D_ERROR', { cause: err })
  }
}

try { doWork() } catch (err) {
  console.log(err)
  switch (err.message) {
    case 'TYPE_C_ERROR': handleFailC(err.cause); break
    case 'TYPE_D_ERROR': handleFailD(err.cause); break
  }
}
function handleFailC(err) { }
function handleFailD(err) { }

上面代码执行结果:

Error: TYPE_C_ERROR
    at doWork (/path/to/project/src/main.ts:11:11)
    at <anonymous> (/path/to/project/src/main.ts:20:3)
    at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
  [cause]: Error: TYPE_A_ERROR
      at doFailSomeWay (/path/to/project/src/main.ts:2:9)
      at doWork (/path/to/project/src/main.ts:9:9)
      at <anonymous> (/path/to/project/src/main.ts:20:3)
      at ModuleJob.run (node:internal/modules/esm/module_job:194:25)
      at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
    [cause]: 'doFailSomeWay'
  }
}

错误层级展示的兼容性

兼容性方面,NodeJs 在 console 能够展示出错误的层级关系,而各大浏览器除了火狐之外,其他还待支持 (截止2024.4.3)

堆栈解析

可以使用 antfu/error-stack-parser-es 进行堆栈的解析

import { parse } from 'error-stack-parser-es/lite'

const stacktrace = parse(new Error('BOOM!'))
// [{ file: 'file.js', name: 'method', line: 1, col: 2}]

如果是为了追踪某一对象,可以使用进一步封装的包 antfu/trace-record

Released under the MIT License.