『壹』 電腦彈出JavaScript警告「無法獲取修改密碼強度信息,網路異常」,校園網就上不去了,怎麼辦
可能是修改密碼後延遲問題 建議先用網頁登錄, 大概 半天的時間在用客戶端登陸 客戶端的密碼同時也要修改
『貳』 javascript中非同步操作的異常怎麼處理
一、JavaScript非同步編程的兩個核心難點
非同步I/O、事件驅動使得單線程的JavaScript得以在不阻塞UI的情況下執行網路、文件訪問功能,且使之在後端實現了較高的性能。然而非同步風格也引來了一些麻煩,其中比較核心的問題是:
1、函數嵌套過深
JavaScript的非同步調用基於回調函數,當多個非同步事務多級依賴時,回調函數會形成多級的嵌套,代碼變成
金字塔型結構。這不僅使得代碼變難看難懂,更使得調試、重構的過程充滿風險。
2、異常處理
回調嵌套不僅僅是使代碼變得雜亂,也使得錯誤處理更復雜。這里主要講講異常處理。
二、異常處理
像很多時髦的語言一樣,JavaScript 也允許拋出異常,隨後再用一個try/catch
語句塊捕獲。如果拋出的異常未被捕獲,大多數JavaScript環境都會提供一個有用的堆棧軌跡。舉個例子,下面這段代碼由於'{'為無效JSON
對象而拋出異常。
?
12345678
function JSONToObject(jsonStr) { return JSON.parse(jsonStr);}var obj = JSONToObject('{');//SyntaxError: Unexpected end of input//at Object.parse (native)//at JSONToObject (/AsyncJS/stackTrace.js:2:15)//at Object.<anonymous> (/AsyncJS/stackTrace.js:4:11)
堆棧軌跡不僅告訴我們哪裡拋出了錯誤,而且說明了最初出錯的地方:第4 行代碼。遺憾的是,自頂向下地跟蹤非同步錯誤起源並不都這么直截了當。
非同步編程中可能拋出錯誤的情況有兩種:回調函數錯誤、非同步函數錯誤。
1、回調函數錯誤
如果從非同步回調中拋出錯誤,會發生什麼事?讓我們先來做個測試。
?
1234567
setTimeout(function A() { setTimeout(function B() { setTimeout(function C() { throw new Error('Something terrible has happened!'); }, 0); }, 0);}, 0);
上述應用的結果是一條極其簡短的堆棧軌跡。
?
12
Error: Something terrible has happened!at Timer.C (/AsyncJS/nestedErrors.js:4:13)
等等,A 和B 發生了什麼事?為什麼它們沒有出現在堆棧軌跡中?這是因為運行C 的時候,非同步函數的上下文已經不存在了,A 和B 並不在內存堆棧里。這3
個函數都是從事件隊列直接運行的。基於同樣的理由,利用try/catch
語句塊並不能捕獲從非同步回調中拋出的錯誤。另外回調函數中的return也失去了意義。
?
1234567
try { setTimeout(function() { throw new Error('Catch me if you can!'); }, 0);} catch (e) {console.error(e);}
看到這里的問題了嗎?這里的try/catch 語句塊只捕獲setTimeout函數自身內部發生的那些錯誤。因為setTimeout
非同步地運行其回調,所以即使延時設置為0,回調拋出的錯誤也會直接流向應用程序。
總的來說,取用非同步回調的函數即使包裝上try/catch 語句塊,也只是無用之舉。(特例是,該非同步函數確實是在同步地做某些事且容易出錯。例如,Node
的fs.watch(file,callback)就是這樣一個函數,它在目標文件不存在時會拋出一個錯誤。)正因為此,Node.js
中的回調幾乎總是接受一個錯誤作為其首個參數,這樣就允許回調自己來決定如何處理這個錯誤。
2、非同步函數錯誤
由於非同步函數是立刻返回的,非同步事務中發生的錯誤是無法通過try-catch來捕捉的,只能採用由調用方提供錯誤處理回調的方案來解決。
例如Node中常見的function (err, ...)
{...}回調函數,就是Node中處理錯誤的約定:即將錯誤作為回調函數的第一個實參返回。再比如HTML5中FileReader對象的onerror函數,會被用於處理非同步讀取文件過程中的錯誤。
舉個例子,下面這個Node 應用嘗試非同步地讀取一個文件,還負責記錄下任何錯誤(如「文件不存在」)。
?
1234567
var fs = require('fs'); fs.readFile('fhgwgdz.txt', function(err, data) { if (err) { return console.error(err); }; console.log(data.toString('utf8'));});
客戶端JavaScript 庫的一致性要稍微差些,不過最常見的模式是,針對成敗這兩種情形各規定一個單獨的回調。jQuery 的Ajax
方法就遵循了這個模式。
?
1234
$.get('/data', { success: successHandler, failure: failureHandler});
不管API 形態像什麼,始終要記住的是,只能在回調內部處理源於回調的非同步錯誤。
三、未捕獲異常的處理
如果是從回調中拋出異常的,則由那個調用了回調的人負責捕獲該異常。但如果異常從未被捕獲,又會怎麼樣?這時,不同的JavaScript環境有著不同的游戲規則……
1. 在瀏覽器環境中
現代瀏覽器會在開發人員控制台顯示那些未捕獲的異常,接著返回事件隊列。要想修改這種行為,可以給window.onerror
附加一個處理器。如果windows.onerror 處理器返回true,則能阻止瀏覽器的默認錯誤處理行為。
?
123
window.onerror = function(err) { return true; //徹底忽略所有錯誤};
在成品應用中, 會考慮某種JavaScript 錯誤處理服務, 譬如Errorception。Errorception
提供了一個現成的windows.onerror 處理器,它向應用伺服器報告所有未捕獲的異常,接著應用伺服器發送消息通知我們。
2. 在Node.js 環境中
在Node 環境中,window.onerror 的類似物就是process 對象的uncaughtException 事件。正常情況下,Node
應用會因未捕獲的異常而立即退出。但只要至少還有一個uncaughtException 事件處理
器,Node 應用就會直接返回事件隊列。
?
123
process.on('uncaughtException', function(err) { console.error(err); //避免了關停的命運!});
但是,自Node 0.8.4 起,uncaughtException 事件就被廢棄了。據其文檔所言,對異常處理而言,uncaughtException
是一種非常粗暴的機制,請勿使用uncaughtException,而應使用Domain 對象。
Domain 對象又是什麼?你可能會這樣問。Domain 對象是事件化對象,它將throw 轉化為'error'事件。下面是一個例子。
?
123456789
var myDomain = require('domain').create();myDomain.run(function() { setTimeout(function() { throw new Error('Listen to me!') }, 50);});myDomain.on('error', function(err) { console.log('Error ignored!');});
源於延時事件的throw 只是簡單地觸發了Domain 對象的錯誤處理器。
Error ignored!
很奇妙,是不是?Domain 對象讓throw
語句生動了很多。不管在瀏覽器端還是伺服器端,全局的異常處理器都應被視作最後一根救命稻草。請僅在調試時才使用它。
四、幾種解決方案
下面對幾種解決方案的討論主要集中於上面提到的兩個核心問題上,當然也會考慮其他方面的因素來評判其優缺點。
1、Async.js
首先是Node中非常著名的Async.js,這個庫能夠在Node中展露頭角,恐怕也得歸功於Node統一的錯誤處理約定。
而在前端,一開始並沒有形成這么統一的約定,因此使用Async.js的話可能需要對現有的庫進行封裝。
Async.js的其實就是給回調函數的幾種常見使用模式加了一層包裝。比如我們需要三個前後依賴的非同步操作,採用純回調函數寫法如下:
?
12345678910111213141516
asyncOpA(a, b, (err, result) => { if (err) { handleErrorA(err); } asyncOpB(c, result, (err, result) => { if (err) { handleErrorB(err); } asyncOpB(d, result, (err, result) => { if (err) { handlerErrorC(err); } finalOp(result); }); });});
如果我們採用async庫來做:
?async.waterfall([ (cb) => { asyncOpA(a, b, (err, result) => { cb(err, c, result); }); }, (c, lastResult, cb) => { asyncOpB(c, lastResult, (err, result) => { cb(err, d, result); }) }, (d, lastResult, cb) => { asyncOpC(d, lastResult, (err, result) => { cb(err, result); }); }], (err, finalResult) => { if (err) { handlerError(err); } finalOp(finalResult);});
可以看到,回調函數由原來的橫向發展轉變為縱向發展,同時錯誤被統一傳遞到最後的處理函數中。
其原理是,將函數數組中的後一個函數包裝後作為前一個函數的末參數cb傳入,同時要求:
每一個函數都應當執行其cb參數;cb的第一個參數用來傳遞錯誤。我們可以自己寫一個async.waterfall的實現:
?let async = { waterfall: (methods, finalCb = _emptyFunction) => { if (!_isArray(methods)) { return finalCb(new Error('First argument to waterfall must be an array of functions')); } if (!methods.length) { return finalCb(); } function wrap(n) { if (n === methods.length) { return finalCb; } return function (err, ...args) { if (err) { return finalCb(err); } methods[n](...args, wrap(n + 1)); } } wrap(0)(false); }};
Async.js還有series/parallel/whilst等多種流程式控制制方法,來實現常見的非同步協作。
Async.js的問題:
在外在上依然沒有擺脫回調函數,只是將其從橫向發展變為縱向,還是需要程序員熟練非同步回調風格。
錯誤處理上仍然沒有利用上try-catch和throw,依賴於「回調函數的第一個參數用來傳遞錯誤」這樣的一個約定。
2、Promise方案
ES6的Promise來源於Promise/A+。使用Promise來進行非同步流程式控制制,有幾個需要注意的問題,
把前面提到的功能用Promise來實現,需要先包裝非同步函數,使之能返回一個Promise:
?
12345678910
function toPromiseStyle(fn) { return (...args) => { return new Promise((resolve, reject) => { fn(...args, (err, result) => { if (err) reject(err); resolve(result); }) }); };}
這個函數可以把符合下述規則的非同步函數轉換為返回Promise的函數:
回調函數的第一個參數用於傳遞錯誤,第二個參數用於傳遞正常的結果。接著就可以進行操作了:
?
123456789101112131415
let [opA, opB, opC] = [asyncOpA, asyncOpB, asyncOpC].map((fn) => toPromiseStyle(fn)); opA(a, b) .then((res) => { return opB(c, res); }) .then((res) => { return opC(d, res); }) .then((res) => { return finalOp(res); }) .catch((err) => { handleError(err); });
通過Promise,原來明顯的非同步回調函數風格顯得更像同步編程風格,我們只需要使用then方法將結果傳遞下去即可,同時return也有了相應的意義:
在每一個then的onFullfilled函數(以及onRejected)里的return,都會為下一個then的onFullfilled函數(以及onRejected)的參數設定好值。
如此一來,return、try-catch/throw都可以使用了,但catch是以方法的形式出現,還是不盡如人意。
3、Generator方案
ES6引入的Generator可以理解為可在運行中轉移控制權給其他代碼,並在需要的時候返回繼續執行的函數。利用Generator可以實現協程的功能。
將Generator與Promise結合,可以進一步將非同步代碼轉化為同步風格:
?
1234567891011
function* getResult() { let res, a, b, c, d; try { res = yield opA(a, b); res = yield opB(c, res); res = yield opC(d); return res; } catch (err) { return handleError(err); }}
然而我們還需要一個可以自動運行Generator的函數:
?
2324252627282930
function spawn(genF, ...args) { return new Promise((resolve, reject) => { let gen = genF(...args); function next(fn) { try { let r = fn(); if (r.done) { resolve(r.value); } Promise.resolve(r.value) .then((v) => { next(() => { return gen.next(v); }); }).catch((err) => { next(() => { return gen.throw(err); }) }); } catch (err) { reject(err); } } next(() => { return gen.next(undefined); }); });}
用這個函數來調用Generator即可:
?
1234567
spawn(getResult) .then((res) => { finalOp(res); }) .catch((err) => { handleFinalOpError(err); });
可見try-catch和return實際上已經以其原本面貌回到了代碼中,在代碼形式上也已經看不到非同步風格的痕跡。
類似的功能有co/task.js等庫實現。
4、ES7的async/await
ES7中將會引入async function和await關鍵字,利用這個功能,我們可以輕松寫出同步風格的代碼,
同時依然可以利用原有的非同步I/O機制。
採用async function,我們可以將之前的代碼寫成這樣:
?
12345678910111213
async function getResult() { let res, a, b, c, d; try { res = await opA(a, b); res = await opB(c, res); res = await opC(d); return res; } catch (err) { return handleError(err); }} getResult();
和Generator & Promise方案看起來沒有太大區別,只是關鍵字換了換。
實際上async
function就是對Generator方案的一個官方認可,將之作為語言內置功能。
async function的缺點:
await只能在async function內部使用,因此一旦你寫了幾個async function,或者使用了依賴於async
function的庫,那你很可能會需要更多的async function。
目前處於提案階段的async
function還沒有得到任何瀏覽器或Node.JS/io.js的支持。Babel轉碼器也需要打開實驗選項,並且對於不支持Generator的瀏覽器來說,還需要引進一層厚厚的regenerator
runtime,想在前端生產環境得到應用還需要時間。
以上就是本文的全部內容,希望對大家的學習有所幫助。
『叄』 jquery或者js如何判斷當前網路是否暢通,我的頁面是給手機用的
代碼邏輯如下:
jQuery.ajax({
url:"",
dataType:"",
type:"",
success:function(data){
//...調用成功代碼
},
error:function(XMLHttpRequest,textStatus,errorThrown){
alert(XMLHttpRequest.status);//查看請求狀態
//調用失敗代碼
}
});
通過ajax的error參數判斷當前網路狀況。
『肆』 怎麼用js腳本判斷自動檢測網路連接是否正常
用AJAX
『伍』 使用JS在瀏覽器中判斷當前網路連接狀態的幾種方法
通過navigator.onLine判斷當前網路狀態:
if(navigator.onLine){
...}else{ ...}
非常簡單,但是並不準確-根據MDN的描述:
navigator.onLine只會在機器未連接到區域網或路由器時返回false,其他情況下均返回true。
也就是說,機器連接上路由器後,即使這個路由器沒聯通網路,navigator.onLine仍然返回true。
『陸』 如何更好地用JavaScript中的異常拋出
雖然最近幾年JavaScript有了很多進步,但是相比於其它語言的開發者,JavaScript開發者仍然只有少得可憐的調試工具。因此在JavaScript中throw
error就顯得比其它語言更有價值。我們可以用throw關鍵字來拋出一個對象。我們可以拋出任何類型的對象,不過Error對象是最常用的:
throw new Error("Something bad happened.")
當我們用這樣的方式拋出錯誤,而這個錯誤又不被try-catch捕獲時,瀏覽器就會用其通常的方式顯示上面的錯誤信息(Something
bad
happened)。在IE里會在瀏覽器的左下角出現一個小圖標,當雙擊圖標時會彈出一個帶著上面錯誤提示的對話框;安裝有Firebug插件的火狐瀏覽器會在控制台顯示錯誤信息;Safar和Chrome會在Web
Inspector中顯示;Opera會在錯誤控制台顯示。一句話,它們會像你沒有拋出錯誤時一樣處理。但不同的是它會通過瀏覽器向你提供具體的信息,而不是一個發生錯誤的行列號。你可以為錯誤信息加入任何需要的信息,來幫你成功解決問題。我建議在錯誤信息中提供發生錯誤的函數名稱以及錯誤原因。看下面這個函數:
function addClass(element, className){
element.className += " " + className;
}
這個函數的功能是向一個給定的element加入新的CSS
class(這在JavaScript中非常普遍)。但如果element是null的時候會發生什麼?你會得到一個這樣的錯誤提示「object
expected」,很隱晦。然後你需要查看執行堆棧(如果瀏覽器支持這個功能)來准確定位錯誤的源頭。如果我們拋出一個錯誤調試就變得簡單了:
function addClass(element, className){
if (element != null && typeof element.className == "string"){
element.className += " " + className;
} else {
throw new Error("addClass(): First arg must be a DOM element.");
}
}
先不討論如何精確的判斷對象是否是一個DOM
element,這個方法現在能夠在非法的element參數傳入時提供一個更明確的錯誤信息。看到了如此詳盡的錯誤描述你就能立刻找到錯誤的源頭了。我習慣把throw
error看作是貼一個任務貼紙,告訴我錯誤的原因。
懂得了如何throw error只是事情的一半;懂得何時throw
error則是另一半。因為JavaScript並不對參數進行類型檢查,許多開發者都錯誤的認為他們應該在所有的函數中進行該檢查。那樣的話是不實際的,而且會降低腳本的執行效率。問題的關鍵在於找到最有可能出錯的代碼部分,並且只在那裡throw
error。一句話就是只在已經發生error的地方throw error。
如果一個函數只被一個已知的實體調用,那麼錯誤檢查基本上是沒有必要的(例如私有函數就是這樣);如果你不能事先確定所有函數被調用的地點,那麼你需要進行錯誤檢查並throw自己的error。throw
error最好的地方是功能函數,那些是腳本環境基本組成部分的,而且可以在任意地點被調用的函數。JavaScript的庫函數就是這樣的例子。
所有JavaScript的庫函數都應當為已知的錯誤條件從它們的公共介面throw
error。對於YUI,jQuery以及Dojo等等,我們無法確定會在何時何處調用它們的庫函數。所以當你犯錯時對你進行提示就是這些庫函數的任務。為什麼呢?因為你不可能到庫函數內部去找出錯誤所在。error的調用堆棧應當終止於庫函數介面,不要再深入。沒有什麼比在12層函數嵌套中尋找錯誤更遭的事了;庫函數開發人員有責任預防這種事情的發生。
這一條同樣適用於私有的JavaScript庫函數。許多Web應用程序都有它們自己專屬的JavaScript庫,可能是通過這些庫來構建的,也可能是用庫來代替公共的操作。庫函數的作用是降低開發難度,這是通過向人們提供其抽象表達而不是復雜的實現細節來實現的。throw
error可以讓這些復雜的實現隱藏在安全的地方不被開發者發現。
JavaScript同樣提供了try-catch語句,用來在瀏覽器處理之前捕獲被throw的error。開發者常常會為到底是僅僅throw
error還是用try-catch將其捕獲而猶豫不決。我們應當只在程序棧的最底層throw
error,就像前面提到的,最典型的就是JavaScript庫函數。所有應用程序都應當在邏輯上具有處理error的能力,因此應當在底層模塊中捕獲error。
在應用程序邏輯中我們總是知道為什麼要調用某個函數,因此它們非常適合處理error。有一點要引起注意,就是永遠不要在try-catch結構中使用空的catch語句;你應當用某種方法處理錯誤。這鍾處理在開發中和最終生產時會有些不同,但必須進行處理。當錯誤發生時,不應當僅僅將其包裹在try-catch里不管——這是掩蓋錯誤而不是解決錯誤。
在JavaScript中throw error是一門藝術。在代碼中找到適當的throw error的地點會花費一些時間。不過一旦你找到了這些地點,你的調試時間就會大大降低,而你對代碼的滿意度會獲得提升。
『柒』 很抱歉,您的電腦或所在的區域網絡有異常的訪問,此刻我們無法響應您的請求.
目前,當某個IP段在短時間內向網路發出大量連接請求,即會受到網路區域網異常訪問屏蔽策略的限制。
有兩個方法可以解決:
1.PHP抓取頁面受限的破解方法
在使用PHP抓取網路知道問題頁時,由於PHP程序抓取速度過快,導致被屏蔽,採用以下的方式解決
抓取頁面需採用fsockopen方式,使用file_get_contents無法設置請求頭
fsockopen函數的使用方法請自行查閱,例子中的geturlcont函數為自定義函數,核心即為fsockopen,geturlcont函數的原型
geturlcont($url, $referer = "" ,$cookie),$url為待抓取的頁面的url,$referer為傳遞的referer參數(主要用於防止抓到的是網路首頁),$cookie為重要的一個參數,用於破解區域網異常訪問屏蔽功能
2.Chrome擴展直接跳轉方案
在另一個程序中,不需要抓取頁面內容,但會同時打開數十頁的網路頁面,同樣可能會造成短時間內請求過多導致的屏蔽,解決方法是通過Chrome擴展的js注入功能實現
附(網路屏蔽頁的代碼):
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>網路--您的訪問出錯了</title>
<style>
body{text-align:center;margin-top:3px}
#wrap{width:650px;text-align:left;margin:auto}
#logo{float:left;margin:0 3px 0 0}
#logo img{border:0}
#title{float:left;width:510px}
#intitle{margin:20px 0 0 0;background-color:#e5ecf9;width:100%;font-weight:bold;font-size:14px;padding:3px 0 4px 10px}
#content{clear:left;padding-top:60px;line-height:200%}
#vf{margin-top:10px}
#vf img{float:left;border:1px solid #000}
#kw{font:16px Verdana;height:1.78em;padding-top:2px}
#vf form{float:left;margin:12px 0 0 5px;padding:0}
#ft{text-align:center}
#ft,#ft a{color:#666;font-size:14px}
</style>
</head>
<body>
<div id="wrap">
<div id="logo"><a href="http://www..com"><img alt="到網路首頁" title="到網路首頁" src="http://www..com/img/logo-yy.gif" width="137" height="46"></a></div>
<div id="title"><div id="intitle">您的訪問出錯了</div></div>
<div id="content">很抱歉,您的電腦或所在的區域網絡有異常的訪問,此刻我們無法響應您的請求。 <br>請輸入以下驗證碼,即可恢復使用。</div>
<div id="vf">
<img src="http://verify..com/cgi-bin/genimg?" width="120" height="40">
<form action="http://verify..com/verify">
<input type="hidden" name="url" value="http://..com/question/519848902?oldq=1&vf_tf=1">
<input type="hidden" name="vcode" value="">
<input type="hidden" name="id" value="1359359285">
<input type="hidden" name="di" value="530e060fe3c68f3d">
<input type="text" size="6" maxlength="10" name="verifycode" id="kw">
<input type="submit" value="提交">
</form>
</div>
<div style="clear:left;height:90px"></div>
<div id="ft">© 2012 Bai <a href="http://www..com/ty/index.html">免責聲明</a></div>
</div>
<script>
(function(){
var rfr = window.document.location.href,
p = encodeURIComponent(rfr),
img = new Image(),
imgzd = new Image(),
re = /\/vcode\?http:\/\/(\S+)\./ig,r="";
img.src = "http://nsclick..com/v.gif?pid=201&pj=vcode&path="+p+"&t="+new Date().getTime();
r = re.exec(rfr);
if(r&&r[1]){imgzd.src = "http://"+r[1]+"..com/v.gif?fr=vcode&url="+p+"&t="+new Date().getTime();}
})();
</script>
</body>
</html>
『捌』 您的電腦或所在的區域網絡有異常的訪問,此刻我們無法響應您的請求。 請輸入以下驗證碼,即可恢復使用。
如果是電信或聯通的ADSL用戶,重新撥號一下應該就沒問題了。
網路可能是檢測到有來自這個公共IP中的異常訪問。
哈哈,如果你是鐵通用戶,那就恭喜你啦!因為鐵通用戶的數據都是經過鐵通NAT轉發過去的,也就是說同一個地區很多可能會共用一個ip(盡管你是公網IP,但是經過nat轉發之後,伺服器看到的是那個公用ip),這樣無論你如何輸入驗證碼,網路可能都會判斷有異常訪問的!
『玖』 JavaScript警告1.1.1.3無法獲取修改密碼強度信息,網路異常。怎麼處理
內網升級改造的問題,屬於系統原因,需要聯系內網總機處理。
『拾』 Node.js 中的未捕獲異常怎麼解決
1. 未捕獲異常帶來的問題
由於 Node.js 的單線程特性,未捕獲異常是一個應用開發過程中值得注意的問題。Node.js 遵循錯誤第一,數據第二的回調模式。我們經常在看到這樣的例子:當回調函數返回一個錯誤對象,那就立即拋出這個錯誤。
如果你運行這個程序,而且假設你沒有somefile.txt這個文件,一個錯誤將被拋出。
Error: ENOENT, open'somefile.txt'這將導致進程崩潰進而影響到整個APP。
這是有意為之,Node.js 不打算把你的應用和服務分隔開。
2. 怎樣處理未捕獲異常
處理未捕獲異常的最佳方式是什麼呢?有非常多方法:
你的應用不應該有未捕獲錯誤,這很瘋狂。
你應該讓你的應用在崩潰後找到未捕獲異常,然後修復它們,這也很瘋狂。
對錯誤視而不見,不處理它—這是大多數人做的,然而這糟透了。
你應該讓你的應用在崩潰後列印出錯誤日誌,然後借用upstart,forever,monit之類的東西重啟進程。這個方法很實用。
【譯者註:現已廢棄】你應該開始使用 Domains 模塊來處理錯誤,這是必由之路,雖然這還是 Node.js 的一個試驗性功能。
現在我們來詳細展開這些方法。
3. 一個沒有未捕獲異常的應用
「沒有未捕獲異常的應用」這個概念對我來說很怪異,任何應用在某個時刻都會有異常而且可能是未捕獲的異常。如果你堅持這個觀點並把錯誤扔給用戶,那麼我覺得你要做好半夜接到電話被告知服務崩潰掉了的准備。
4. 使你的應用崩潰
The only defence I can find in this opinion is the fail fast argument. You are going to fix your application quickly if it unavailable. If an application without uncaught exceptions is denial letting your application crash is acceptance. But you are still pushing exception handling onto your users.(原諒我實在想不出怎麼翻譯這段,如果你有好的想法,請盡快聯系我!)
5. 假裝沒看見錯誤?
很多人這樣做:
1這很糟糕,當一個未捕獲異常被拋出,你應該意識到你的應用處在一個不正常的狀態,這種情況下你無法可靠地運行你的程序。
最初提出 process.on 事件的Felix Geisendörfer現在倡議去除它。
6. 應用崩潰,列印日誌,然後重啟
通過這個方法你可以讓你的應用在發生未捕獲異常時立即崩潰,然後利用forever或upstart這樣的工具(幾乎可以)立即重啟。Node.js 將會把異常寫入STERR所以你可以把異常重定向到一個日誌文件稍晚再通過它拿到錯誤。這種方法的缺點是,對於錯誤發生在你的代碼之外的i/o,不能提供一種優雅的方法來處理臨時停電或者網路i/o出錯的場景。這真是一個利器!— 重啟應用並重試。如果你把這種策略與cluster mole相結合,node 可以自動重啟任何拋出錯誤的 children 並且列印出錯誤。
7. 使用Domains模塊【譯者註:現已廢棄】
Domains是Node.js v0.8版本中新增的一個試驗性特性,它使得異常處理變得更加靈活和精確。下面是剛才那個文件不存在的例子,通過使用domains你可以為一個特定的 domain 觸發 error 事件,你還可以針對不同的場景使用不同的異常處理。這使得你根據異常的發生地點來對應地處理它們。如果退出進程像是用榔頭敲碎堅果,那麼這就像一把精確的手術刀為你提供對程序完全的控制。
8. 結論
如果你在產品環境運行 Node.js 你起碼應該對如何處理異常有一個想法。目前為止我相信當異常被拋出時,大多數人只是重啟應用(也許是優雅地重啟),Domains為應用提供了一種更聰明的面對異常的能力,異常處理器可能會選擇簡單的清理、關閉某些連接,最壞的情況下,退出進程。關鍵點就在於你有了選擇。