как избежать явного построения анти-паттерна и при этом держать отступы / обратные вызовы на низком уровне - PullRequest
0 голосов
/ 29 мая 2019

Допустим, у нас есть функция, которая вызывает значительное количество асинхронных функций, например:

downloadAndAssemble = () => 
  new Promise(async (resolve, reject) => {

    if (!(await checkAvailableDiskSpace())) {
      resolve(false);
      return;
    }

    try {
      // Download all
      let files  = await this.downloadAll();

      // Assemble File from downloaded snippets.
      const assembledFile = await buildFile(files).catch(error => reject(error));

      // Save assembled file.
      resolve(true);
    } catch (err) {
      reject(err);
    } finally {
      const dirExists = await fs.exists(tmpFolderPath);
      if (dirExists) await fs.unlink(tmpFolderPath);
    }
  });

Первая проблема, которую я вижу, это new Promise(async (resolve, reject) => {, которая является анти-паттерном согласно этой статье SO .

Общая идея, которую я получил из этой статьи, состоит в том, чтобы повторно использовать обещания, если они доступны, а не создавать новые.

Если я следую предложениям в этом ответе SO , я должен использовать .then и .catch в логическом потоке функции, чтобы использовать существующие Обещания.

Но это привело бы к большему количеству отступов (то есть по одному на каждое обещание), которые, как я думал, обещания должны помочь устранить.

Как вы можете видеть из .catch(error => reject(error)) код не очень совместим с обработкой ошибок, возникающих из-за содержащихся в нем обещаний.

1 Ответ

1 голос
/ 29 мая 2019
  downloadAndAssemble = async () =>  {
    if (!(await checkAvailableDiskSpace())) {
      return false;
    }

     try {
       // Download all
       let files  = await this.downloadAll();

       // Assemble File from downloaded snippets.
       const assembledFile = await buildFile(files);

      // Save assembled file.
      return true;
    } finally {
       const dirExists = await fs.exists(tmpFolderPath);
       if (dirExists) await fs.unlink(tmpFolderPath);
    }
};

Если вы вызываете функцию async, она неявно создаст для вас обещание, которое разрешается, если вы return, и отклоняет, если вы throw, поэтому нет необходимости создавать иуправлять обещанием «вручную».

.catch(error => reject(error)) не имеет большого смысла, так как await обещание автоматически позволяет пузырям ошибок возникать.В вашем коде это обходит try { ... } catch { ... }, который, вероятно, не нужен.

То же самое относится к } catch (err) { reject(err); }, await - это все, что вам нужно.

...