2017-07-08 38 views
2

我試圖遞歸地走一個目錄樹並收集所有的文件名。在下面的代碼,但是,console.log()末運行太早,而不是等待通過函數的遞歸調用cacheDir產生的承諾來解決:等待,直到所有的承諾已經解決了遞歸走的目錄

function cacheDir(dir) { 
    return fs.readdir(dir).then(items => { 
    const readDirPromises = [] 

    for (let item of items) { 
     const fullPath = path.join(dir, item) 
     const lstat = fs.lstat(fullPath) 
     readDirPromises.push(lstat) 

     lstat.then(stats => { 
     if (stats.isFile()) { 
      return fullPath 
     } else { 
      return cacheDir(fullPath) 
     } 
     }) 
    } 

    return Promise.all(readDirPromises) 
    }) 
} 

cacheDir("../someDir/") 
    .then(results => console.log('done!', results)) 

我在做什麼錯?在我看來,readDirPromises將是一個strings和承諾的數組,每個承諾本身將解析爲一個字符串和承諾數組。

回答

3

您等待Promise.all()的承諾需要爲lstat.then(),而不僅僅是lstat。請記住,lstat.then()會返回一個新的承諾,並且新承諾會跟蹤由於遞歸而需要處理的.then()處理程序中返回的任何承諾。

這裏有一個版本,這是否(以及擺脫一些臨時變量):

function cacheDir(dir) { 
    return fs.readdir(dir).then(items => { 
    const readDirPromises = []; 

    for (let item of items) { 
     const fullPath = path.join(dir, item); 

     readDirPromises.push(fs.lstat(fullPath).then(stats => { 
     if (stats.isFile()) { 
      return fullPath; 
     } else { 
      return cacheDir(fullPath); 
     } 
     })); 
    } 

    return Promise.all(readDirPromises) 
    }) 
} 
+0

感謝,並沒有意識到,'那麼()'返回一個新的承諾! – maxedison

+0

@maxedison - 這就是鏈接工程的承諾。新返回的promise會等待'.then()'返回的任何承諾,因此您會得到一個鏈。 – jfriend00