1. 程式人生 > >那些年,在nodejs上踩過的坑

那些年,在nodejs上踩過的坑

原文:http://cnodejs.org/topic/4fc7789a8be5d070121141cd

-----------------------------------------------------------

自己寫nodejs也有一段時間,踩過很多坑(而且大部分是自己給自己埋),也見過很多別人踩過的坑,原因其實也很簡單,要麼是對這個知識點理解不夠深入,要麼就是編碼的習慣不好。這段響應朋春大牛的號召,打算陸陸續續整理下這些坑,算是給自己一個備忘,同時也希望能對大家有所幫助。

1. callback

事件回撥是nodejs非常常見的一個應用場景,那大家先來看看以下這段程式碼是否存在什麼問題?

get(params,function(err, data){if(err){
   callback(err);}//對data進行操作var row = data[0];});

看出來了吧。對,就是err存在時,callback之後,接下來的程式碼還是要執行的。而這時,data值是什麼,我們往往是沒辦法控制的。如果data這時返回的是undefined,那麼就悲劇了,程式肯定報錯。當然解決方法很簡單,就是在callback之前加個return即可:

get(params,function(err, data){if(err){return callback(err);}//對data進行操作var
row = data[0];});

這個知識點並不是很難,但往往是初學者特別容易犯的錯,甚至已經寫了很久程式碼的同學也會偶爾犯這種低階錯誤。

再來一個更隱蔽的:

db.get(key,function(err, data){if(err){return callback(err);}try{
    callback(null, JSON.parse(data.toString()))}catch(e){
    callback(e);}});

看似沒有任何問題吧。嘿嘿,揭曉答案, 對,被回撥兩次。callback(null, Error)一次,callback(e),具體比如:

function
asyncfun(data, callback){try{ callback(null, JSON.parse(data.toString()));}catch(e){ callback(e);}}var json ={'a':'b'};var jsonstr = JSON.stringify(json);var d =newBuffer(jsonstr); asyncfun(d,function(err, data){ console.log(err);thrownewError('new Error');});

執行結果:

null[Error:newError]

這在一個大專案絕對是坑爹了,排錯都需要很久。

ps:之前的描述存在問題,謝謝蘇千的指正。

2. buffer

還是老規矩,先看程式碼:

var data ="";  
res.on('data',function(chunk){  
  data += chunk;}).on("end",function(){});

這段程式碼在chunk都是ascii碼資料或者資料量比較少時是沒有問題,但如果你的資料是大量中文的話,恭喜你,中槍了,會出現亂碼。其原因是兩個chunk(Buffer物件)的拼接並不正常,相當於進行了buffer.toString() + buffer.toString()。如果buffer不是完整的,則toString出來後的string是存在問題的(比如一箇中文字被截斷)。具體可以參見樸靈寫得這篇文章:http://cnodejs.org/topic/4faf65852e8fb5bc65113403

3. 深度巢狀

很多剛開始寫nodejs程式碼的人,由於思路還停留在同步的思維,所以或多或少寫過這樣的程式碼:

func1(err,function(err1, data1){
  func2(err1,function(err2, data2){
    func3(err3,function(err3, data3){
      func4(err4,function(err4, data4){.......})})})})

先別說這樣的程式碼是否易於維護,光樣子就夠難看,程式碼都“斜”了。不怕大家恥笑,我自己剛開始就寫時也寫過這樣“坑爹”的程式碼,為此自己當時還寫了篇《如何讓nodejs同步操作》講如何解決這個問題。不過從源頭上,大家還是要儘量避免採用這種同步的方法,因為nodejs得優勢就在於非同步,硬生生要做成同步絕對吃力不討好