1. 程式人生 > >Node.js Errors模組

Node.js Errors模組

Errors

  • Error Propagation and Interception
    • Node.js style callbacks
  • Class: Error
    • new Error(message)
    • Error.captureStackTrace(targetObject[, constructorOpt])
    • Error.stackTraceLimit
      • error.message
      • error.stack
  • Class: RangeError
  • Class: ReferenceError
  • Class: SyntaxError
  • Class: TypeError
  • Exceptions vs. Errors
  • System Errors
    • Class: System Error
      • error.code
      • error.errno
      • error.syscall
    • Common System Errors

Errors

錯誤;過失;失誤;

Applications running in Node.js will generally experience four categories of errors:

  • Standard JavaScript errors such as:
    • <EvalError> : thrown when a call to eval() fails.
    • <SyntaxError> : thrown in response to improper JavaScript language syntax.
    • <RangeError> : thrown when a value is not within an expected range
    • <ReferenceError> : thrown when using undefined variables
    • <TypeError> : thrown when passing arguments of the wrong type
    • <URIError> : thrown when a global URI handling function is misused.
  • System errors triggered by underlying operating system constraints such as attempting to open a file that does not exist, attempting to send data over a closed socket, etc;
  • And User-specified errors triggered by application code.
  • Assertion Errors are a special class of error that can be triggered whenever Node.js detects an exceptional logic violation that should never occur. These are raised typically by the assert module.

All JavaScript and System errors raised by Node.js inherit from, or are instances of, the standard JavaScript class and are guaranteed to provide at least the properties available on that class.

執行在Node.js上的程式,通常會經歷這4個型別的錯誤。

  • 標準的JavaScript錯誤如下:

    • <EvalError>: 當eval() 函式執行失敗時被丟擲。eval() 函式可計算某個字串,並執行其中的的 JavaScript 程式碼(如果有的話)。
    • <SyntaxError>: 響應不合適的JavaScript語法時被丟擲。
    • <RangeError>: 當一個值不在預期的範圍內時被丟擲。
    • <ReferenceError>: 當使用未定義的變數時被丟擲。
    • <TypeError>: 當轉換錯誤型別的引數時被丟擲。
    • <URIError>: 當一個全域性的URI處理函式被誤用時丟擲。
  • 系統錯誤是由底層作業系統約束引起的,比如嘗試去開啟一個不存在的檔案,嘗試在一個已經關閉的套接字上傳送資料,等等。

  • 使用者自定義錯誤是由應用程式錯誤碼引起的。
  • 斷言錯誤是一個特殊的錯誤類,每當Node.js檢測到一個例外的邏輯違反時就會觸發,但它不應該被觸發。這類錯誤通常由斷言模組引起。

Node.js中所有被丟擲的JavaScript和系統的錯誤都繼承自或者由JavaScript的<Error>類例項化,並且保證提供至少一個可以獲取的屬性。

Error Propagation and Interception

錯誤繼承和攔截

Node.js supports several mechanisms for propagating and handling errors that occur while an application is running. How these errors are reported and handled depends entirely on the type of Error and the style of the API that is called.

All JavaScript errors are handled as exceptions that immediately generate and throw an error using the standard JavaScript throw mechanism. These are handled using the try / catch construct provided by the JavaScript language.

Node.js支援多種繼承機制和在程式執行時的錯誤處理。異常如何報告並且如果處理完全依賴於錯誤的型別和被呼叫的API的風格。

所有的JavaScript的錯誤都被當做即時生成的異常處理並且使用標準的JavaScript機制丟擲異常。它們可以使用JavaScript語言提供的try/catch建構函式來處理。

// Throws with a ReferenceError because z is undefined
// 丟擲一個引用異常,因為z未定義
try {
  const m = 1;
  const n = m + z;
} catch (err) {
  // Handle the error here.
  //在這裡處理異常
}

Any use of the JavaScript throw mechanism will raise an exception that must be handled using try / catch or the Node.js process will exit immediately.

With few exceptions, Synchronous APIs (any blocking method that does not accept a callback function, such as fs.readFileSync), will use throw to report errors.

Errors that occur within Asynchronous APIs may be reported in multiple ways:

任何使用JavaScript的丟擲機制都會產生一個異常,必須使用try/catch來處理,否則Node.js程序就會立即退出。

少數的異常,同步APIs(任何不接受回撥函式的阻塞方法,比如fs.readFileSync)都會使用丟擲的方式來報告異常。

非同步APIs裡產生的錯誤可能會通過多種方式進行報告。

  • Most asynchronous methods that accept a callback function will accept an Error object passed as the first argument to that function. If that first argument is not null and is an instance of Error, then an error occurred that should be handled.

大部分非同步方法都接受一個回撥函式,該函式接收一個錯誤物件作為它的第一個引數。如果第一個引數不是null,並且是錯誤物件的例項,就表示有一個需要被處理的錯誤產生了。

const fs = require('fs');
fs.readFile('a file that does not exist', (err, data) => {
  if (err) {
    console.error('There was an error reading the file!', err);
    return;
  }
  // Otherwise handle the data
});
  • When an asynchronous method is called on an object that is an EventEmitter, errors can be routed to that object’s ‘error’ event.

當事件發生器物件上的一個非同步方法被呼叫時,錯誤會被路由到那個物件的錯誤事件上。

const net = require('net');
const connection = net.connect('localhost');

// Adding an 'error' event handler to a stream:
//為這個流新增錯誤事件處理
connection.on('error', (err) => {
  // If the connection is reset by the server, or if it can't connect at all, or on any sort of error encountered by the connection, the error will be sent here.
  //如果連線被伺服器重置,或者根本不能連線,或者連線遭遇到了任何形式的錯誤,錯誤就會被送到這裡。
  console.error(err);
});

connection.pipe(process.stdout);
  • A handful of typically asynchronous methods in the Node.js API may still use the throw mechanism to raise exceptions that must be handled using try / catch. There is no comprehensive list of such methods; please refer to the documentation of each method to determine the appropriate error handling mechanism required.

在Node.js API中少許典型的非同步方法可能還在使用丟擲機制來產生異常,它必須使用try / catch來處理。並沒有這樣的方法的綜合列表;可以參考每個方法的文件來判斷所需的合適的異常處理機制。

The use of the ‘error’ event mechanism is most common for stream-based and event emitter-based APIs, which themselves represent a series of asynchronous operations over time (as opposed to a single operation that may pass or fail).

For all EventEmitter objects, if an ‘error’ event handler is not provided, the error will be thrown, causing the Node.js process to report an unhandled exception and crash unless either: The domain module is used appropriately or a handler has been registered for the process.on('uncaughtException') event.

使用錯誤事件機制在基於流和基於事件觸發的API中是最為常見的。它們自身逐漸代表了一系列的非同步操作(而不是單一的操作,可能通過或失敗)。

對於所有事件觸發器物件,如果沒有提供錯誤事件的處理器,錯誤就將會被丟擲,導致Node.js執行緒報告一個未捕獲的異常同時崩潰,除非:整個模組都被恰當的使用或者已經註冊了process.on('uncaughtException')的事件處理器。

var myEvent = new events.EventEmitter();
setImmediate(()=>{
    // This will crash the process because no 'error' event handler has been added.
    //執行緒將會崩潰,因為沒有'error'事件捕獲機制被新增。
    myEvent.emit('error', new Error('This will crash'));
});

Errors generated in this way cannot be intercepted using try / catch as they are thrown after the calling code has already exited.

Developers must refer to the documentation for each method to determine exactly how errors raised by those methods are propagated.

以這種方式產生的錯誤不能被try/catch攔截,因為它們是在呼叫的大媽執行結束後才被丟擲的。

開發者一定要參考每一個方法的文件來恰當地決定如何傳遞這些方法引起的錯誤。

Node.js style callbacks

Most asynchronous methods exposed by the Node.js core API follow an idiomatic pattern referred to as a “Node.js style callback”. With this pattern, a callback function is passed to the method as an argument. When the operation either completes or an error is raised, the callback function is called with the Error object (if any) passed as the first argument. If no error was raised, the first argument will be passed as null.

大部分由Node.js核心API暴露的非同步方法都遵循一個符合Node.js回撥風格的語言模式。使用該模式,回撥函式可以作為一個引數被傳遞。當操作完成或者錯誤產生以後,該回調函式就會被呼叫,帶一個錯誤物件(如果有的話)作為第一個引數。如果沒錯誤產生,第一個引數就會傳空。

const fs = require('fs');

function nodeStyleCallback(err, data) {
 if (err) {
   console.error('There was an error', err);
   return;
 }
 console.log(data);
}

fs.readFile('/some/file/that/does-not-exist', nodeStyleCallback);
fs.readFile('/some/file/that/does-exist', nodeStyleCallback)

The JavaScript try / catch mechanism cannot be used to intercept errors generated by asynchronous APIs. A common mistake for beginners is to try to use throw inside a Node.js style callback:

JavaScript try / catch 機制不能用來攔截由非同步API產生的錯誤。一個初學者常犯的錯誤是嘗試在Node.js風格的回撥函式中使用丟擲。

// This will not work
const fs = require('fs');

try {
  fs.readFile('/some/file/that/does-not-exist', (err, data) => {
    // mistaken assumption: throwing here...
    if (err) {
      throw err;
    }
  });
} catch(err) {
  // This will not catch the throw!
  console.log(err);
}

This will not work because the callback function passed to fs.readFile() is called asynchronously. By the time the callback has been called, the surrounding code (including the try { } catch(err) { } block will have already exited. Throwing an error inside the callback can crash the Node.js process in most cases. If domains are enabled, or a handler has been registered with process.on('uncaughtException'), such errors can be intercepted.

它並不能正常工作,因為傳遞給fs.readFile()的回撥函式會被非同步地呼叫。等到回撥函式被呼叫的時候,周圍的程式碼(包括try { } catch(err) { } 程式碼塊早都執行完了)。大多數情況下,在回撥函式中丟擲異常會導致Node.js程序崩潰。如果啟用了域,或者已經註冊了process.on('uncaughtException'),這樣的錯誤就會被截斷。

Class: Error

A generic JavaScript Error object that does not denote any specific circumstance of why the error occurred. Error objects capture a “stack trace” detailing the point in the code at which the Error was instantiated, and may provide a text description of the error.

All errors generated by Node.js, including all System and JavaScript errors, will either be instances of, or inherit from, the Error class.

new Error(message)

Creates a new Error object and sets the error.message property to the provided text message. If an object is passed as message, the text message is generated by calling message.toString(). The error.stack property will represent the point in the code at which new Error() was called. Stack traces are dependent on V8’s stack trace API. Stack traces extend only to either (a) the beginning of synchronous code execution, or (b) the number of frames given by the property Error.stackTraceLimit, whichever is smaller.

Error.captureStackTrace(targetObject[, constructorOpt])

Creates a .stack property on targetObject, which when accessed returns a string representing the location in the code at which Error.captureStackTrace() was called.

const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack  // similar to `new Error().stack`

The first line of the trace, instead of being prefixed with ErrorType: message, will be the result of calling targetObject.toString().

The optional constructorOpt argument accepts a function. If given, all frames above constructorOpt, including constructorOpt, will be omitted from the generated stack trace.

The constructorOpt argument is useful for hiding implementation details of error generation from an end user. For instance:

function MyError() {
  Error.captureStackTrace(this, MyError);
}

// Without passing MyError to captureStackTrace, the MyError
// frame would show up in the .stack property. By passing
// the constructor, we omit that frame and all frames above it.
new MyError().stack

Error.stackTraceLimit

error.message

error.stack

Class: RangeError

Class: ReferenceError

Class: SyntaxError

Class: TypeError

Exceptions vs. Errors

System Errors

Class: System Error

error.code

error.errno

error.syscall

Common System Errors