簡體   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