2017-05-03 64 views
0

我越來越多地瞭解節點,我遇到的最大問題是確定異步函數是如何工作的。異步函數 - 這是'回調地獄'嗎?

fs.readdir(base, function (err, files) { 
    if (!files.length) { 
     console.log('No files'); 
    } 
    for (var i in files) { 
     fs.stat(files[i], function (err, stats) { 
      if (stats.isDirectory()) { 
       console.log(files[i]); 
       console.log('FOLDER'); 
      } else { 
       console.log(files[i]); 
       console.log('FILE') 
      } 
     }) 
    } 
}); 

base是有兩個子文件夾中,並且.DS_Store文件的文件夾。在命令行輸出將是:

.DS_Store 
FILE 
/dir/to/file/index.js:115 
     if (stats.isDirectory()) { 
      ^

TypeError: Cannot read property 'isDirectory' of undefined 

我的基本認識是現在存在這個問題,因爲這一切都是異步發生的一切 - 我最好的猜測是,readdir回調不「等待」爲fs.stat回調結束?我可能會完全誤解它(實際上,從基礎知識中學習的任何好文檔都會有所幫助)。

我的下一個想法就像承諾一樣?他們似乎用異步解決了很多問題,這將是我下一次學習的飛躍。

這是'回撥地獄'嗎?承諾修復?有沒有不同的方式來做到這一點?

+0

您可以使用承諾來解決問題,或者您可以在本文中使用不同的方法。請詳細介紹。 http://justincalleja.com/2015/03/08/sequential-control-flow-with-lodash-or-underscore/#The_approach –

+4

不,這裏的問題似乎是帽子有一個錯誤「statting」之一文件,所以'stats'不會被設置。如果'err'爲'null',你應該只能訪問它。解決方案:做適當的錯誤處理,不要忽略'err'。 –

+0

(是的,承諾可以解決這個問題,如果正確應用) – Bergi

回答

0

根據您的其他代碼,這裏可能存在一些問題。一個是fs.stat將路徑作爲第一個參數,而不是文件名。如果您將函數調用更改爲fs.stat(base + '/' + files[i], function (err, stats)可能有所幫助。但我不確定base在你的例子中。其次,你應該在循環中使用ES6 let而不是var。異步函數將被放置在調用堆棧上,並在完成時按順序處理。然而,那時循環將一直運行,變量i將等於它在上一次迭代中的值。另一方面,用let定義的變量在範圍上受限於塊,這意味着每個函數由於位於單獨的塊中而具有正確的值i

嘗試測試下面這兩個不同的版本,首先用for (var i in files),然後用for (let i in files),你會明白我的意思。

for (var i in files) { 
     fs.stat(files[i], function (err, stats) { 
      if (stats.isDirectory()) { 
       console.log(files[i]); 
       console.log('FOLDER'); 
       console.log(i); 
      } else { 
       console.log(files[i]); 
       console.log('FILE') 
       console.log(i); 
      } 
     }) 
    } 

此外,正如您對我的問題的意見建議,我會建議你做適當的錯誤處理。

+0

非常感謝你,你用'fs.stat'的要求來釘住它。我應該放慢腳步,再讀一遍文件。你也教過我一兩課! – vSanjo