Node.js API詳解之 Error模塊用法實(shí)例分析
本文實(shí)例講述了Node.js API詳解之 Error模塊用法。分享給大家供大家參考,具體如下:
Node.js API詳解之 Error
Node.js 中運(yùn)行的應(yīng)用程序一般會(huì)遇到以下四類(lèi)錯(cuò)誤:
1.標(biāo)準(zhǔn)的 JavaScript 錯(cuò)誤:
EvalError : 當(dāng)調(diào)用 eval() 失敗時(shí)拋出。
SyntaxError : 當(dāng) JavaScript 語(yǔ)法錯(cuò)誤時(shí)拋出。
RangeError : 當(dāng)值不在預(yù)期范圍內(nèi)時(shí)拋出。
ReferenceError : 當(dāng)使用未定義的變量時(shí)拋出。
TypeError : 當(dāng)傳入錯(cuò)誤類(lèi)型的參數(shù)時(shí)拋出。
URIError : 當(dāng)全局的 URI 處理函數(shù)被誤用時(shí)拋出。
2.由底層操作系觸發(fā)的系統(tǒng)錯(cuò)誤,例如試圖打開(kāi)一個(gè)不存在的文件、試圖通過(guò)一個(gè)已關(guān)閉的 socket 發(fā)送數(shù)據(jù)等。
3.由應(yīng)用程序代碼觸發(fā)的用戶(hù)自定義的錯(cuò)誤。
4.斷言錯(cuò)誤是錯(cuò)誤的一個(gè)特殊類(lèi)別,每當(dāng) Node.js 檢測(cè)到一個(gè)不應(yīng)該發(fā)生的異常邏輯時(shí)觸發(fā)。 這類(lèi)錯(cuò)誤通常由 assert 模塊引起。
所有由 Node.js 引起的 JavaScript 錯(cuò)誤與系統(tǒng)錯(cuò)誤都繼承自或?qū)嵗詷?biāo)準(zhǔn)的 JavaScript 類(lèi),且保證至少提供類(lèi)中的屬性。
錯(cuò)誤的冒泡和捕獲
說(shuō)明:
Node.js 支持幾種當(dāng)應(yīng)用程序運(yùn)行時(shí)發(fā)生的錯(cuò)誤的冒泡和處理的機(jī)制。
如何報(bào)告和處理這些錯(cuò)誤完全取決于錯(cuò)誤的類(lèi)型和被調(diào)用的 API 的風(fēng)格。
所有 JavaScript 錯(cuò)誤都會(huì)被作為異常處理,異常會(huì)立即產(chǎn)生并使用標(biāo)準(zhǔn)的 JavaScript throw 機(jī)制拋出一個(gè)錯(cuò)誤。
這些都是使用 JavaScript 語(yǔ)言提供的 try / catch 語(yǔ)句處理的。
JavaScript 的 throw 機(jī)制的任何使用都會(huì)引起異常,異常必須使用 try / catch 處理,
否則 Node.js 進(jìn)程會(huì)立即退出。
除了少數(shù)例外,同步的 API(任何不接受 callback 函數(shù)的阻塞方法,例如 fs.readFileSync)會(huì)使用 throw 報(bào)告錯(cuò)誤。
大多數(shù)的異步方法都接受一個(gè) callback 函數(shù),該函數(shù)會(huì)接受一個(gè) Error 對(duì)象傳入作為第一個(gè)參數(shù)。
如果第一個(gè)參數(shù)不是 null 而是一個(gè) Error 實(shí)例,則說(shuō)明發(fā)生了錯(cuò)誤,應(yīng)該進(jìn)行處理。例:
const fs = require('fs'); fs.readFile('一個(gè)不存在的文件', (err, data) => { if (err) { console.error('讀取文件出錯(cuò)!', err); return; } // 否則處理數(shù)據(jù) });
當(dāng)一個(gè)異步方法被一個(gè) EventEmitter 對(duì)象調(diào)用時(shí),錯(cuò)誤會(huì)被分發(fā)到對(duì)象的 ‘error' 事件上。例:
const net = require('net'); const connection = net.connect('localhost'); // 添加一個(gè) 'error' 事件句柄到一個(gè)流: connection.on('error', (err) => { // 如果連接被服務(wù)器重置,或無(wú)法連接,或發(fā)生任何錯(cuò)誤,則錯(cuò)誤會(huì)被發(fā)送到這里。 console.error(err); }); connection.pipe(process.stdout);
Node.js API 中有一小部分普通的異步方法仍可能使用 throw 機(jī)制拋出異常,且必須使用 try / catch 處理。
這些方法并沒(méi)有一個(gè)完整的列表;請(qǐng)參閱各個(gè)方法的文檔以確定所需的合適的錯(cuò)誤處理機(jī)制。
對(duì)于所有的 EventEmitter 對(duì)象,如果沒(méi)有提供一個(gè) ‘error' 事件句柄,則錯(cuò)誤會(huì)被拋出,
并造成 Node.js 進(jìn)程報(bào)告一個(gè)未處理的異常且隨即崩潰,除非: 適當(dāng)?shù)厥褂?domain 模塊或已經(jīng)注冊(cè)了一個(gè) process.on(‘uncaughtException') 事件的句柄。
const EventEmitter = require('events'); const ee = new EventEmitter(); setImmediate(() => { // 這會(huì)使進(jìn)程崩潰,因?yàn)檫€為添加 'error' 事件句柄。 ee.emit('error', new Error('這會(huì)崩潰')); });
這種方式產(chǎn)生的錯(cuò)誤無(wú)法使用 try / catch 截獲,因?yàn)樗鼈兪窃谡{(diào)用的代碼已經(jīng)退出后拋出的。
開(kāi)發(fā)者必須查閱各個(gè)方法的文檔以明確在錯(cuò)誤發(fā)生時(shí)這些方法是如何冒泡的。
Error 類(lèi)
說(shuō)明:
一個(gè)通用的 JavaScript Error 對(duì)象,它不表示錯(cuò)誤發(fā)生的具體情況。
Error 對(duì)象會(huì)捕捉一個(gè)“堆棧跟蹤”,詳細(xì)說(shuō)明被實(shí)例化的 Error 對(duì)象在代碼中的位置,并可能提供錯(cuò)誤的文字描述。
只對(duì)于加密,如果在拋出錯(cuò)誤時(shí)可以使用 Error 對(duì)象,則會(huì)將OpenSSL錯(cuò)誤堆棧放入到名為 opensslErrorStack 的單獨(dú)屬性中。
所有由 Node.js 產(chǎn)生的錯(cuò)誤,包括所有系統(tǒng)的和 JavaScript 的錯(cuò)誤都實(shí)例化自或繼承自 Error 類(lèi)。
new Error(message)
說(shuō)明:
新建一個(gè) Error 實(shí)例,并設(shè)置 error.message 屬性以提供文本信息。
如果 message 傳的是一個(gè)對(duì)象,則會(huì)調(diào)用 message.toString() 生成文本信息。
error.stack 屬性表示被調(diào)用的 new Error() 在代碼中的位置。
堆棧跟蹤是基于 V8 的堆棧跟蹤 API 的。
堆棧跟蹤只會(huì)?。╝)異步代碼執(zhí)行的開(kāi)頭或(b)Error.stackTraceLimit 屬性給出的棧幀中的最小項(xiàng)。
demo:
throw new Error('異常信息'); // Error: 異常信息 // at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:1:69) // at Module._compile (module.js:660:30) // at Object.Module._extensions..js (module.js:671:10) // at Module.load (module.js:573:32) // at tryModuleLoad (module.js:513:12) // at Function.Module._load (module.js:505:3) // at Function.Module.runMain (module.js:701:10) // at startup (bootstrap_node.js:193:16) // at bootstrap_node.js:617:3
Error.stackTraceLimit
說(shuō)明:
Error.stackTraceLimit 屬性指定了堆棧跟蹤收集的棧幀數(shù)量
(無(wú)論是 new Error().stack 或 Error.captureStackTrace(obj) 產(chǎn)生的)。
默認(rèn)值為 10 ,但可設(shè)為任何有效的 JavaScript 數(shù)值。 值改變后的變化會(huì)影響所有捕獲到的堆棧跟蹤。
如果設(shè)為一個(gè)非數(shù)值或負(fù)數(shù),則堆棧跟蹤不會(huì)捕捉任何棧幀。
demo:
Error.stackTraceLimit = 5; try{ const a = 1 + b; }catch(err){ console.log(err.stack); } // ReferenceError: b is not defined // at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:3:16) // at Module._compile (module.js:660:30) // at Object.Module._extensions..js (module.js:671:10) // at Module.load (module.js:573:32) // at tryModuleLoad (module.js:513:12)
Error.captureStackTrace(targetObject[, constructorOpt])
說(shuō)明:
在 targetObject 上創(chuàng)建一個(gè) .stack 屬性
當(dāng)訪(fǎng)問(wèn)時(shí)返回一個(gè)表示代碼中調(diào)用 Error.captureStackTrace() 的位置的字符串。
可選的 constructorOpt 參數(shù)接受一個(gè)函數(shù)。 如果提供了,則 constructorOpt 之上包括自身在內(nèi)的全部棧幀都會(huì)被生成的堆棧跟蹤省略。
demo:
const myObject = {}; Error.captureStackTrace(myObject); console.log( myObject.stack ); // Error // at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:7) // at Module._compile (module.js:660:30) // at Object.Module._extensions..js (module.js:671:10) // at Module.load (module.js:573:32) // at tryModuleLoad (module.js:513:12) // at Function.Module._load (module.js:505:3) // at Function.Module.runMain (module.js:701:10) // at startup (bootstrap_node.js:193:16) // at bootstrap_node.js:617:3
error.code
說(shuō)明:
error.code 屬性是標(biāo)識(shí)錯(cuò)誤類(lèi)別的字符標(biāo)簽。
詳見(jiàn) Node.js Error Codes
demo: try{ const a = 1 + b; }catch(err){ console.log(err.code); } // undefined
error.message
說(shuō)明:
error.message 屬性是錯(cuò)誤的字符串描述,通過(guò)調(diào)用 new Error(message) 設(shè)置。
傳給構(gòu)造函數(shù)的 message 也會(huì)出現(xiàn)在 Error 的堆棧跟蹤的第一行。
但是,Error 對(duì)象創(chuàng)建后改變這個(gè)屬性可能不會(huì)改變堆棧跟蹤的第一行(比如當(dāng) error.stack 在該屬性被改變之前被讀?。?。
demo:
try{ const a = 1 + b; }catch(err){ console.log(err.message); } // b is not defined
error.stack
說(shuō)明:
error.stack 屬性是一個(gè)字符串,描述代碼中 Error 被實(shí)例化的位置。
第一行會(huì)被格式化為 : ,
且?guī)弦幌盗袟恳恍卸家?“at ” 開(kāi)頭)。 每一幀描述了一個(gè)代碼中導(dǎo)致錯(cuò)誤生成的調(diào)用點(diǎn)。
V8 引擎會(huì)試圖顯示每個(gè)函數(shù)的名稱(chēng)(變量名、函數(shù)名、或?qū)ο蟮姆椒?,但偶爾也可能找不到一個(gè)合適的名稱(chēng)。
如果 V8 引擎沒(méi)法確定一個(gè)函數(shù)的名稱(chēng),則只顯示幀的位置信息。 否則,在位置信息的旁邊會(huì)顯示明確的函數(shù)名。
注意,幀只由 JavaScript 函數(shù)產(chǎn)生。
demo:
try{ const a = 1 + b; }catch(err){ console.log(err.stack); } // ReferenceError: b is not defined // at Object. (/Users/xiaoqiang/Documents/work/demo/NodeApi/app.js:2:16) // at Module._compile (module.js:660:30) // at Object.Module._extensions..js (module.js:671:10) // at Module.load (module.js:573:32) // at tryModuleLoad (module.js:513:12) // at Function.Module._load (module.js:505:3) // at Function.Module.runMain (module.js:701:10) // at startup (bootstrap_node.js:193:16) // at bootstrap_node.js:617:3
AssertionError 類(lèi)
說(shuō)明:
Error 的子類(lèi),表示斷言失敗。 這種錯(cuò)誤通常表示實(shí)際值和預(yù)期值不相等。
demo:
const assert = require('assert'); assert.strictEqual(1, 2); // AssertionError [ERR_ASSERTION]: 1 === 2
RangeError 類(lèi)
說(shuō)明:
Error 的一個(gè)子類(lèi),表明一個(gè)函數(shù)的一個(gè)給定的參數(shù)的值不在可接受的集合或范圍內(nèi);
無(wú)論是一個(gè)數(shù)字范圍還是給定函數(shù)參數(shù)的選項(xiàng)的集合。
demo:
require('net').connect(-1); // RangeError [ERR_SOCKET_BAD_PORT]: Port should be > 0 and < 65536. Received -1.
ReferenceError 類(lèi)
說(shuō)明:
Error 的一個(gè)子類(lèi),表明試圖訪(fǎng)問(wèn)一個(gè)未定義的變量。 這些錯(cuò)誤通常表明代碼有拼寫(xiě)錯(cuò)誤或程序已損壞。
雖然客戶(hù)端代碼可能產(chǎn)生和傳播這些錯(cuò)誤,但在實(shí)踐中,只有 V8 引擎會(huì)這么做。
demo:
console.log( a ); // ReferenceError: a is not defined
SyntaxError 類(lèi)
說(shuō)明:
Error 的一個(gè)子類(lèi),表明程序不是有效的 JavaScript 代碼。 這些錯(cuò)誤是代碼執(zhí)行的結(jié)果產(chǎn)生和傳播的。
代碼執(zhí)行可能產(chǎn)生自 eval、Function、require 或 vm。 這些錯(cuò)誤幾乎都表明程序已損壞。
demo:
eval('**'); // SyntaxError: Unexpected token **
TypeError 類(lèi)
說(shuō)明:
Error 的一個(gè)子類(lèi),表明提供的參數(shù)不是一個(gè)被允許的類(lèi)型。
例如,將一個(gè)函數(shù)傳給一個(gè)期望字符串的參數(shù)會(huì)被視為一個(gè) TypeError。
demo:
require('url').parse(() => { }); // TypeError [ERR_INVALID_ARG_TYPE]: The "url" argument must be of type string. Received type function
System Error 類(lèi)
說(shuō)明:
系統(tǒng)錯(cuò)誤是當(dāng)程序運(yùn)行環(huán)境中發(fā)生異常時(shí)產(chǎn)生的。
有單獨(dú)的異常類(lèi),并且有單獨(dú)的屬性:
error.code屬性是一個(gè)表示錯(cuò)誤碼的字符串,總是 E 帶上一串大寫(xiě)字母。
error.errno屬性是一個(gè)數(shù)值或字符串。 如果返回一個(gè)數(shù)值,則數(shù)值是一個(gè)負(fù)數(shù),
對(duì)應(yīng) libuv 錯(cuò)誤處理 中定義的錯(cuò)誤碼。 如果返回一個(gè)字符串,則同 error.code。
error.syscall屬性是一個(gè)字符串,描述失敗的 系統(tǒng)調(diào)用。
error.path屬性是一個(gè)字符串,包含了相關(guān)不可用路徑名。
error.address屬性是對(duì)鏈接失敗的地址的描述。
error.port是一個(gè)鏈接端口不可用的端口值
異常與錯(cuò)誤
說(shuō)明:
JavaScript 異常是一個(gè)作為一個(gè)無(wú)效操作的結(jié)果或作為一個(gè) throw 聲明的目標(biāo)所拋出的值。
雖然它不要求這些值是 Error 的實(shí)例或繼承自 Error 的類(lèi)的實(shí)例,
但所有通過(guò) Node.js 或 JavaScript 運(yùn)行時(shí)拋出的異常都是 Error 實(shí)例。
有些異常在 JavaScript 層是無(wú)法恢復(fù)的。 這些異常總會(huì)引起 Node.js 進(jìn)程的崩潰。
例如 assert() 檢測(cè)或在 C++ 層調(diào)用的 abort()。
系統(tǒng)錯(cuò)誤
說(shuō)明:
系統(tǒng)錯(cuò)誤是當(dāng)程序運(yùn)行環(huán)境中發(fā)生異常時(shí)產(chǎn)生的。
特別是,當(dāng)應(yīng)用程序違反了操作系統(tǒng)的限制時(shí)發(fā)生的操作錯(cuò)誤,例如試圖讀取一個(gè)不存在的文件或用戶(hù)沒(méi)有足夠的權(quán)限。
系統(tǒng)錯(cuò)誤通常產(chǎn)生于系統(tǒng)調(diào)用層級(jí)。
在大多數(shù) Unix 系統(tǒng)上,可通過(guò)運(yùn)行 man 2 intro、man 3 errno、或在線(xiàn)文檔獲取錯(cuò)誤代碼的詳細(xì)清單和含義。
系統(tǒng)錯(cuò)誤是由擴(kuò)展的 Error 對(duì)象加上附加屬性表現(xiàn)的。
常見(jiàn)的系統(tǒng)錯(cuò)誤:
以下列表是不完整的,但列舉了編寫(xiě) Node.js 程序時(shí)會(huì)遇到的一些常見(jiàn)的系統(tǒng)錯(cuò)誤。 詳細(xì)的列表可從 ERRNO 文檔找到。
EACCES (拒絕訪(fǎng)問(wèn)): 試圖以被一個(gè)文件的訪(fǎng)問(wèn)權(quán)限禁止的方式訪(fǎng)問(wèn)一個(gè)文件。EADDRINUSE (地址已被使用): 試圖綁定一個(gè)服務(wù)器(net、http 或 https)到本地地址,但因另一個(gè)本地系統(tǒng)的服務(wù)器已占用了該地址而導(dǎo)致失敗。
ECONNREFUSED (連接被拒絕): 無(wú)法連接,因?yàn)槟繕?biāo)機(jī)器積極拒絕。 這通常是因?yàn)樵噲D連接到外部主機(jī)上的廢棄的服務(wù)。
ECONNRESET (連接被重置): 一個(gè)連接被強(qiáng)行關(guān)閉。 這通常是因?yàn)檫B接到遠(yuǎn)程 socket 超時(shí)或重啟。 常發(fā)生于 http 和 net 模塊。
EEXIST (文件已存在): 一個(gè)操作的目標(biāo)文件已存在,而要求目標(biāo)不存在。
EISDIR (是一個(gè)目錄): 一個(gè)操作要求一個(gè)文件,但給定的路徑是一個(gè)目錄。
EMFILE (系統(tǒng)打開(kāi)了太多文件): 已達(dá)到系統(tǒng)文件描述符允許的最大數(shù)量,且描述符的請(qǐng)求不能被滿(mǎn)足直到至少關(guān)閉其中一個(gè)。 當(dāng)一次并行打開(kāi)多個(gè)文件時(shí)會(huì)發(fā)生這個(gè)錯(cuò)誤,尤其是在進(jìn)程的文件描述限制數(shù)量較低的操作系統(tǒng)(如 macOS)。 要解決這個(gè)限制,可在運(yùn)行 Node.js 進(jìn)程的同一 shell 中運(yùn)行 ulimit -n 2048。
ENOENT (無(wú)此文件或目錄): 通常是由 fs 操作引起的,表明指定的路徑不存在,即給定的路徑找不到文件或目錄。
ENOTDIR (不是一個(gè)目錄): 給定的路徑雖然存在,但不是一個(gè)目錄。 通常是由 fs.readdir 引起的。
ENOTEMPTY (目錄非空): 一個(gè)操作的目標(biāo)是一個(gè)非空的目錄,而要求的是一個(gè)空目錄。 通常是由 fs.unlink 引起的。
EPERM (操作不被允許): 試圖執(zhí)行一個(gè)需要更高權(quán)限的操作。
EPIPE (管道損壞): 寫(xiě)入一個(gè)管道、socket 或 FIFO 時(shí)沒(méi)有進(jìn)程讀取數(shù)據(jù)。 常見(jiàn)于 net 和 http 層,表明遠(yuǎn)端要寫(xiě)入的流已被關(guān)閉。
ETIMEDOUT (操作超時(shí)): 一個(gè)連接或發(fā)送的請(qǐng)求失敗,因?yàn)檫B接方在一段時(shí)間后沒(méi)有做出合適的響應(yīng)。 常見(jiàn)于 http 或 net。 往往標(biāo)志著 socket.end() 沒(méi)有被正確地調(diào)用
希望本文所述對(duì)大家node.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
Node.js的文件權(quán)限及讀寫(xiě)flag詳解
Node.js對(duì)文件的讀寫(xiě)還是相當(dāng)靈活的,因?yàn)樽约豪鲜怯洸蛔∥募蚰夸洐?quán)限的數(shù)值表達(dá)和字符表達(dá)。所以整理出這篇文章,方便以后查閱,下面來(lái)一起看看吧。2016-10-10Node.js實(shí)現(xiàn)簡(jiǎn)單聊天服務(wù)器
Node.js 是一個(gè)基于Chrome JavaScript運(yùn)行時(shí)建立的一個(gè)平臺(tái), 用來(lái)方便地搭建快速的,易于擴(kuò)展的網(wǎng)絡(luò)應(yīng)用,今天我們來(lái)探討下,如何使用node.js實(shí)現(xiàn)簡(jiǎn)單的聊天服務(wù)器2014-06-06node.js中的path.resolve方法使用說(shuō)明
這篇文章主要介紹了node.js中的path.resolve方法使用說(shuō)明,本文介紹了path.resolve的方法說(shuō)明、接收參數(shù)、語(yǔ)法、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12Node.js 使用 cors 中間件解決跨域問(wèn)題小結(jié)
cors 是 Express 的一個(gè)第三方中間件,通過(guò)安裝和配置 cors 中間件,可以很方便地解決跨域問(wèn)題,本文介紹Node.js 使用 cors 中間件解決跨域問(wèn)題,感興趣的朋友一起看看吧2024-01-01websocket+node.js實(shí)現(xiàn)實(shí)時(shí)聊天系統(tǒng)問(wèn)題咨詢(xún)
最近新學(xué)習(xí)websocket,做了一個(gè)實(shí)時(shí)聊天。用Node.js搭建的服務(wù):serevr.js. 兩個(gè)相互通信頁(yè)面:client.html 和server.html 但是就是有很多問(wèn)題,下面通過(guò)本文給大家分享下2017-05-05Node.JS段點(diǎn)續(xù)傳:Nginx配置文件分段下載功能的實(shí)現(xiàn)方法
在Node.JS中可以配置這個(gè)標(biāo)簽來(lái)實(shí)現(xiàn)文件的分段下載。這篇文章給大家介紹了Node.JS段點(diǎn)續(xù)傳:Nginx配置文件分段下載功能的實(shí)現(xiàn)方法,需要的朋友參考下吧2018-03-03node使用mysql獲取數(shù)據(jù)庫(kù)數(shù)據(jù)中文亂碼問(wèn)題的解決
這篇文章主要介紹了node使用mysql獲取數(shù)據(jù)庫(kù)數(shù)據(jù)中文亂碼問(wèn)題的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Sublime Text3 配置 NodeJs 環(huán)境的方法
大家都知道,Sublime Text 安裝插件一般從 Package Control 中直接安裝即可,當(dāng)我安裝 node js 插件時(shí)候,直接通過(guò)Package Control 安裝,雖然插件安裝成功了,但是找不到配置文件 Nodejs.sublime-build 來(lái)更改一些配置2020-05-05