2015-11-24 65 views
0

我在閱讀firefox-json-bookmarks的節點腳本中有一個simlple異步閱讀器。 當我刪除回調函數中的第一個參數(錯誤),我得到一個錯誤。 是什麼原因?爲什麼err與e不同?爲什麼我需要2個回調參數?

app.js

var fs = require('fs'), obj; 
fs.readFile(__dirname + '/bookmarks.json', 'utf8', handleFile); 

function handleFile(err, data) { // why is the first parameter needed? 

    try { 
     obj = JSON.parse(JSON.stringify(data)); 
     console.log(obj); 

    } catch (e) { 
     console.log(e); 
     //console.log(err); 
    } 
} 
+1

https://www.joyent.com/developers/node/design/errors –

回答

1
每個

調用一個函數時,該函數被壓入的被稱爲調用堆棧功能的堆疊。當該函數返回一個值時,它會彈出堆棧。調用堆棧描述了你在程序中的位置以及你如何到達那裏。

同步碼

通過想象調用堆棧出這個計劃的過程。

function a() { return b() } 
function b() { return c() } 
function c() { throw new Error() } 
a(); 

首先,調用a,所以我們將它添加到堆棧中。

[ a ] 

然後a電話b,所以我們添加到堆棧中了。

[ a, b ] 

然後b調用c

[ a, b, c ] 

然後c將引發錯誤。在這一點上,調試器可以告訴你,c是拋出錯誤的函數,並且你最終在c,通過a然後b。這適用於普通的同步代碼,如JSON.parse

異步代碼

函數返回後異步代碼繼續運行。例如:

function a() { 
    setTimeout(function() { console.log(2); }, 10000); 
    return 1; 
} 

如果你打電話a,然後將它推入調用堆棧,然後返回1和被彈出調用堆棧。約10秒後,2將被打印到控制檯中。

如果超時做到了,會發生什麼?

function a() { 
    setTimeout(function() { throw new Error(); }, 10000); 
    return 1; 
} 

錯誤將被拋出,但調用堆棧將爲空。正如你可以想象的,這對開發者來說並不是很有用。

這也是一個問題,如果我們想要異步返回一個值。當異步事件發生時(超時,讀/寫,網絡等),函數已經返回。

取而代之,我們可以使用一種稱爲Continuation-Passing Style的形式,通常稱爲回調。除了調用我們的異步函數外,我們還傳遞函數(繼續),我們要求它在完成時運行。記住,這可以在函數返回一個值之後!

在Node.js的,這些回調一舉兩得:

錯誤

如果出現錯誤,而這樣做的異步工作方式,標準的做法是調用回調與錯誤作爲第一個參數。你會經常看到下面的代碼。

foo.doAsyncBar(function(err, baz) { 
    if(err) throw err; 
    // do something with baz 
}); 

通過傳遞錯誤的回調而不是拋出它,我們能夠做出我們自己的決定如何最好地處理它。我們可以拋出它,如上所示,或者我們可以以更優雅的方式處理它。

返回

希望的功能將不會錯誤,在這種情況下,一般的做法是通過null作爲第一個參數回調。這讓編寫處理代碼的開發人員知道該函數沒有錯誤,並且返回值位於下一個參數之一中。

有關Node.js錯誤處理的更深入的文章,請參閱Joyent的Production Practices document for Errors

+0

謝謝。但它是好的,當我不拋出錯誤,只做:if(err)return console.error(err); ? –

+1

這取決於。這樣你會看到錯誤,但程序可能會停止工作而不會崩潰 - 你可能會開始丟失數據。如果你拋出錯誤,那麼你保證程序將停止。如果這是一個非嚴重錯誤,那麼你可以使用'console.warn'來明確它。 –

相關問題