2017-05-09 53 views
-1

基於在這裏找到的代碼片段在stackoverflow,我想讀取目錄中的所有文件,然後繼續。 我已經添加了一個承諾,但這不知何故無效。爲什麼承諾先解決?

我的目錄包含2個文件和控制檯日誌輸出是:
承諾解決
內部文件名
內部文件名
內readFiles
內readFiles

function readFiles(dirname, onFileContent, onError) { 
    return new Promise((resolve, reject) => { 
     fs.readdir(dirname, function(err, filenames) { 
      filenames.forEach(function(filename) { 

       console.log('inside filenames'); 

       fs.readFile(dirname + filename, 'utf-8', function(err, content) { 
        onFileContent(filename, content); 
       }); 
      }); 
     }); 
    }); 
} 

var data = []; 
readFiles('datadir/', function(filename, content) { 
    console.log('inside readFiles'); 
    data.push(filename); 
}).then(
    console.log('promise resolved'); 
    //proceed handling the data-array 
); 
+0

您的代碼甚至不會用分號執行,但它看起來像你應該有'然後(函數(){'和你剛纔'then'假設有 –

+0

我沒有看到你的承諾 - 你永遠不會解決它,你使用回調來獲取文件內容。 – Jamiec

+0

@Jamiec點的承諾將等到所有文件都被讀取 –

回答

1

的承諾不會「解決第一」。 console.log的呼叫在讀取第一個文件之前執行。

你永遠不會打電話給你的諾言resolve,所以then永遠不會被稱爲。但是,您將結果console.log傳遞給thenconsole.log的結果是無效的。

您可以通過糾正問題測試:

readFiles('datadir/', function(filename, content) { 
    console.log('inside readFiles'); 
    data.push(filename); 
}).then(function(){ // NOTE: addition of function(){..} 
    console.log('promise resolved'); 
    //proceed handling the data-array 
}); 

,你會發現該消息不會被寫入控制檯。


所以這就是最新錯誤 - 如何解決它。需要思考一下,將你的腦袋包裝在節點中完全異步/基於承諾的代碼中。

我假設您要等待全部文件在解析您的承諾之前讀取其中的內容。這有點棘手,因爲你有2個異步調用(讀取文件列表,然後單獨讀取它們的內容)。將文件的閱讀包裝到自己的承諾中可能會更容易。事情是這樣的:

function readFile(filePath){ 
    return new Promise((resolve,reject) => { 
     fs.readFile(filePath, "utf-8", function(err,content) => { 
      if(err) reject(err) 
      else resolve({path:filePath, content:content}) 
     }); 
    }); 
} 

執行相同的readdir,使也可鏈接:

function readDirectory(dir){ 
    return new Promise((resolve,reject) => { 
     fs.readdir(dirname, function(err, filenames) { 
      if(err) reject(err); 
      else{ 
      resolve(filenames.map(fn => dir + fn)); 
      } 
     }); 
    }); 
} 

之所以這樣做是可以再上一個Promise.all鏈,等待所有文件內容。

​​

用法:

readFileContents('datadir/').then(files => { 
    files.forEach(file => { 
     console.log(file.path, file.content.length); 
    }); 
}); 
+0

感謝,作品像一個魅力 –

+0

避免['Promise' constructor antipattern](http://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-避免它)在'readFiles'!你應該創建一個使用promise構造函數的'readDir'函數,然後將它正確地與'readFile'結合到'readFiles'中。 – Bergi

+0

@Bergi - 我認爲這是我用''readFile'方法做的。你能解釋一下「使用承諾構造函數」是什麼意思嗎? – Jamiec