繁体   English   中英

异步/等待过度杀伤? 我是否不必要地使用异步并等待?

[英]Async/Await overkill? Am I unnecessarily using async and await?

我想知道我的小节点脚本是无意义还是过度使用async / await。 我的目标是尝试尽可能并行地查找和解析尽可能多的文件。 我的想法是它会更快。

我的节点脚本遍历目录和任何子目录并查找.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);

当一个特定的代码块需要等待一个Promise 然后在完成之前对它做一些事情 (可能涉及等待另一个 Promise之后)时, await通常很有用。 如果唯一的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);
};

然后,只在入口点catch walkDir的调用:

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的修复)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM