javascript - 异步/等待矫枉过正?我是否不必要地使用异步和等待?

标签 javascript node.js async-await

我想知道我的小 Node 脚本是否毫无意义或过度使用异步/等待。我的目标是尝试尽可能多地并行查找和解析文件。我的想法是它会更快。

我的 Node 脚本遍历目录和任何子目录并查找 .docx 文件。当它找到它们时,它会通过 Mammoth 运行它们。将它们转换成 .html 文件。它只是将它们放在相似的目录结构中。

我的代码可以工作,但我是否过度使用了 async/await?是否有地方我可以消除它们的使用,因为没有理由在我所在的地方使用它们?

const createTempDirs = async (catMap) => {
  try {
    const dirPromises = catMap.map((cat) => fs.mkdir(`issue/${cat.abv}`, {
      recursive: true,
    }));
    await Promise.all(dirPromises);  
  } catch (error) {
    console.log(error);
  }
};

const writeToFile = (fileName) => {
  return async (result) => {
    //return await fs.writeFile(`issue/${fileName.replace('.docx', '.html')}`);
    try {
      const [
        ,
        category,
        ...parts
      ] = fileName.split(' ');
      await createTempDirs(catMap),
      await fs.writeFile(`issue/${getShortCatName(category)}/${fileName.replace('.docx', '.html')}`, result.value);
    } catch (error) {
      console.log(error);
    }
  };
}

const fileToHTML = async (file, dirPath) => {
  try {
    const fileDetails = await fs.lstat(dirPath + file);
    if (fileDetails.isDirectory()) {
      walkDir(dirPath + addTrailingSlash(file));
    }
    if (!fileDetails.isDirectory() && path.extname(file) === '.docx') {
      mammoth.convertToHtml({
        path: dirPath + file,
      }, conversionOptions).then(writeToFile(file));
    }
  } catch (error) {
    console.log(error);
  }
};

const processFiles = async (files, dirPath) => {
  try {
    const filePromises = files.map(file => fileToHTML(file, dirPath));
    return await Promise.all(filePromises);
  } catch (error) {
    console.log(error);
  }
};

const walkDir = async (dirPath) => {
  try {
    const files = await fs.readdir(dirPath);
    processFiles(files, dirPath);
  } catch (error) {
    console.log(error);
  }
};

walkDir(dirPath);

最佳答案

await 通常在特定代码块需要等待 Promise 然后在完成之前用它做一些事情时很有用(可能涉及等待 另一个 事后 promise )。如果唯一的 await 位于函数的最后一行,则返回 Promise 更有意义。

至于try/catch,总体思路是在可以适当处理的级别上捕获错误。因此,例如,如果您想在出现问题时完全停止, catch 在最外层的调用中,例如:

const createTempDirs = (catMap) => Promise.all(
  catMap.map((cat) => fs.mkdir(`issue/${cat.abv}`, {
    recursive: true,
  }))
);

const writeToFile = (fileName) => {
  return async (result) => {
    //return await fs.writeFile(`issue/${fileName.replace('.docx', '.html')}`);
    const [
      ,
      category,
      ...parts
    ] = fileName.split(' ');
    await createTempDirs(catMap);
    await fs.writeFile(`issue/${getShortCatName(category)}/${fileName.replace('.docx', '.html')}`, result.value);
  };
};

const fileToHTML = async (file, dirPath) => {
  const fileDetails = await fs.lstat(dirPath + file);
  if (fileDetails.isDirectory()) {
    // see below line - remember to await or return every Promise created!
    await walkDir(dirPath + addTrailingSlash(file));
  }
  if (!fileDetails.isDirectory() && path.extname(file) === '.docx') {
    // see below line - remember to await or return every Promise created!
    return mammoth.convertToHtml({
      path: dirPath + file,
    }, conversionOptions).then(writeToFile(file));
  }
};

const processFiles = (files, dirPath) => Promise.all(files.map(file => fileToHTML(file, dirPath)));

const walkDir = async (dirPath) => {
  const files = await fs.readdir(dirPath);
  processFiles(files, dirPath);
};

然后,只有入口点的catchwalkDir的调用:

walkDir(dirPath)
  .catch((err) => {
    // There was an error somewhere
  });

如果你想在子调用中出现错误时在某个点继续处理,那么在那个点捕获错误,例如,如果单个 writeFile 可能失败,但你没有不希望错误向上渗透调用链并停止一切,writeFile 的调用者中的 try/catch:

const writeToFile = (fileName) => {
  return async (result) => {
    const [
      ,
      category,
      ...parts
    ] = fileName.split(' ');
    await createTempDirs(catMap);
    try {
      await fs.writeFile(`issue/${getShortCatName(category)}/${fileName.replace('.docx', '.html')}`, result.value);
    } catch(e) {
      // writeFile failed, but the rest of the script will continue on as normal
      // the error, since it was caught here,
      // WILL NOT BE passed up to the caller of writeToFile
    }
  };
};

确保 awaitreturn 您在入口点之后创建的每个 Promise,这样错误就会正确地向上传递到 Promise 链。 (查看对 fileToHTML 所做的修复)

关于javascript - 异步/等待矫枉过正?我是否不必要地使用异步和等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57618626/

相关文章:

javascript - jquery过滤器后面板主体文本区域消失

javascript - Node.js, ajax - 前端路由

javascript - 对于 NodeJs Promise,Await 和 Then 哪个更好?以及等待如何工作

javascript - 调用 setTimeout 时出现 NaN 错误

java - 如何在 Javascript 中重构 "extract function"?

javascript - Chrome、Firefox 和 Opera 中的 CSS 转换问题,但 IE 中没有

python - 为什么 ruby​​ `require` 不是更细粒度的?

javascript - Office365 IMAP 访问 : User is Authenticated but not Connected

c# - 任务 IsCanceled 是假的,而我取消了

c# - 试图让方法等待内部事件处理完成