簡體   English   中英

等待遞歸調用異步 function 的 function

[英]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回調。 您可以將mapPromise.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM