[英]Awaiting a function that calls an async function recursively
我有一個看起來像這樣的 function:
function populateMap(directory: string, map, StringMap) {
fs.promises.readdir(directory).then(files: string[]) => {
files.forEach(file: string) => {
const fullPath = path.join(directory, file);
fs.stat(fullPath, (err: any, stats: any) => {
if (stats.isDirectory()) {
populateFileMap(fullPath, fileMap);
} else {
fileMap[file] = fullPath;
}
});
});
});
}
我想要做的是遞歸遍歷父目錄並將文件名的 map 存儲到它們的路徑中。 我知道這是有效的,因為如果我在 fileMap[file] = fullPath 下放置一個 console.log(fileMap),在目錄中最深的文件之后,列表就會正確填充。
在調用此 function 的文件中,我希望能夠擁有完整的 map
function populateMapWrapper(dir: string) {
const fileMap: StringMap = {};
populateMap(dir, fileMap);
//fileMap should be correctly populated here
}
我嘗試過使populateMap異步,將a.then()添加到包裝器function中調用它的位置,但是如果我在then() function中使用console.log(fileMap),則fileMap為空。
我不確定這是否是因為 javascript 如何傳遞變量,或者我對承諾的理解存在差距,但我想知道是否有其他方法可以做到這一點。
一個問題是fs.stat
沒有返回 promise。 您還需要使用fs.promises.stat
。 此外,在使用 Promise 時要小心使用forEach
,因為它不會await
每個forEach
回調。 您可以將map
與Promise.all()
一起使用
一種解決方案:
function populateMap(directory: string, map) {
return fs.promises.readdir(directory).then((files: string[]) => {
return Promise.all(
files.map((file: string) => {
const fullPath = path.join(directory, file);
return fs.promises.stat(fullPath).then(stats => {
if (stats.isDirectory()) {
return populateMap(fullPath, map);
} else {
map[file] = fullPath;
}
})
}))
})
}
然后你必須在包裝器中使用await
:
async function populateMapWrapper(dir: string) {
const fileMap: StringMap = {};
await populateMap(dir, fileMap);
//fileMap should be correctly populated here
}
但是,更易讀的解決方案是盡可能使用await
。 就像是:
async function populateMap (directory: string, map) {
const files = await fs.promises.readdir(directory)
for (const file of files) {
const fullPath = path.join(directory, file)
const stats = await fs.promises.stat(fullPath)
if (stats.isDirectory()) {
await populateMap(fullPath, map)
} else {
map[file] = fullPath
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.