Skip to content

Latest commit

 

History

History
184 lines (134 loc) · 5.1 KB

File metadata and controls

184 lines (134 loc) · 5.1 KB

Error 对象

概述

Node的异步操作的特性,使得抛出(throw)错误不可行,因为捕捉错误的代码可能已经执行完毕,无法再捕捉错误了。这时,唯一的办法就是将Error对象传给下一个回调函数。

Express的错误中间件。

app.use(function(err, req, res, next) {
  console.error(err.stack);

  // 401, 403, 404 错误不发邮件
  if (!err.statusCode || err.statusCode === 500) {
    emails.error({ err: err, req: req });
  }

  res.send(err.statusCode || 500, err.message);
});

自定义错误

可以用下面的方法,自定义自己的错误对象。

var assert = require('assert');
var util = require('util');

function NotFound(message) {
  Error.call(this);
  this.message = message;
}

util.inherits(NotFound, Error);

var error = new NotFound('/home 没有找到');

上面代码中,error同时是NotFoundError的实例。

stack属性

ECMAScript规格只规定,Error对象的实例必须有message属性,但是各个JavaScript实现往往还添加了堆栈信息。

  • V8引擎是error.stack
  • Firefox也是error.stack,但有自己的格式
  • IE不提供stack属性

以下介绍V8引擎的API,它在Node和Chrome浏览器之中可以使用。

Error.stackTraceLimit

V8默认将调用堆栈限制在10条记录,但是可以在运行时,通过改变Error.stackTraceLimit属性调整这个值。

Error.stackTraceLimit = 0; // 不显示任何堆栈
Error.stackTraceLimit = Infinity; // 堆栈数目不存在任何限制

Error.captureStackTrace()

Error.captureStackTrace方法用来在指定对象上,为stack属性设立一个取值器(getter),返回Error.captureStackTrace方法运行时的堆栈。

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack // 返回代码调用堆栈

上面方法的第二行在myObject对象上,新建一个stack属性,值等于这时Error.captureStackTrace的调用堆栈。

Error.captureStackTrace还可以接受第二个参数,是一个处在调用堆栈上的函数。它的作用是将堆栈上,这个函数及其以上的调用记录都隐藏起来不显示。

function createError(msg, status){
  var err = new Error(msg);
  err.status = status;
  Error.captureStackTrace(err);
  return err;
}

var err = createError('test', 500);
throw err;

// Error: test
//     at createError (/home/admin/x.js:6:9)
//     at Object.<anonymous> (/home/admin/x.js:10:11)
//     at Module._compile (module.js:409:26)
//     ...

上面代码中,堆栈信息最上面一行会显示createError,表示这个错误是在执行createError函数时产生的。现在,为Error.captureStackTrace方法加入第二个参数createError,就可以把这一行隐藏。

function createError(msg, status) {
  var err = new Error(msg);
  err.status = status;
  Error.captureStackTrace(err, createError);
  return err;
}

var err = createError('test', 500);
throw err;

// Error: test
//     at Object.<anonymous> (/home/admin/x.js:10:11)
//     at Module._compile (module.js:409:26)
//     ...

这个错误通常用于自定义错误。

function NotFound(message) {
  Error.call(this);
  Error.captureStackTrace(this, NotFound);
  this.message = message;
  this.statusCode = 404;
}

上面代码定义了一个NotFound对象,它继承了Error对象。需要的时候,就可以抛出这个对象的实例。

Error.prepareStackTrace()

Error.prepareStackTrace方法的作用是,定制err.stack的返回值。

Error.prepareStackTrace = function () {
  return 'MyStackObject';
}

try {
  throw new Error();
} catch (e) {
  console.log(e.stack);
}
// "MyStackObject"

上面代码定制err.stack返回一个字符串MyStackObject

Error.prepareStackTrace方法可以接受两个参数,第一个是错误对象实例,第二个是表示堆栈的数组,它的每个成员都是一个堆栈记录对象,有一些方法可以在这个对象上调用。

function a () {
  b();
}

function b () {
  var err = new Error;

  Error.prepareStackTrace = function (err, stack) {
    return stack;
  };

  Error.captureStackTrace(err, b);

  err.stack.forEach(function (frame) {
    console.error(' call: %s:%d - %s'
      , frame.getFileName()
      , frame.getLineNumber()
      , frame.getFunctionName());
  });
}

a();
//  call: /home/admin/x.js:2 - a
//  call: /home/admin/x.js:22 - null
//  call: module.js:409 - Module._compile
//  call: module.js:416 - Module._extensions..js
//  call: module.js:343 - Module.load
//  call: module.js:300 - Module._load
//  call: module.js:441 - Module.runMain
//  call: node.js:139 - startup
//  call: node.js:968 - null

上面代码中,Error.prepareStackTrace方法定制了err.stack,返回一个数组。该数组的每个成员都有getFileName()getLineNumber()getFunctionName()等方法,可以用来获取文件名、行号、函数名。

参考链接