Рефакторинг сложной вложенной функции Node.js - PullRequest
0 голосов
/ 29 сентября 2018

У меня есть следующий фрагмент кода ниже.В настоящее время он работает, но я надеюсь немного его оптимизировать / реорганизовать.

По сути, он выбирает данные JSON, извлекает URL-адреса для ряда PDF-файлов из ответа, а затем загружает эти PDF-файлы в папку..

Я надеюсь реорганизовать этот код для обработки PDF-файлов после их загрузки.В настоящее время я не уверен, как это сделать.Существует много вложенных асинхронных функций.

Как я могу реорганизовать это, чтобы позволить мне подключиться к другому вызову .then перед моим обработчиком ошибок, чтобы я мог затем обрабатывать PDF-файлы, которые

const axios = require("axios");
const moment = require("moment");
const fs = require("fs");
const download = require("download");
const mkdirp = require("mkdirp"); //  Makes nested files...
const getDirName = require("path").dirname; // Current directory name...

const today = moment().format("YYYY-MM-DD");

function writeFile(path, contents, cb){
  mkdirp(getDirName(path), function(err){
    if (err) return cb(err)
      fs.writeFile(path, contents, cb)
  })
};

axios.get(`http://federalregister.gov/api/v1/public-inspection-documents.json?conditions%5Bavailable_on%5D=${today}`)
  .then((res) => {
    res.data.results.forEach((item) => {
      download(item.pdf_url).then((data) => {
        writeFile(`${__dirname}/${today}/${item.pdf_file_name}`, data, (err) => {
          if(err){
            console.log(err);
          } else {
            console.log("FILE WRITTEN: ", item.pdf_file_name);
          }
        })
      })
    })
  })
  .catch((err) => {
    console.log("COULD NOT DOWNLOAD FILES: \n", err);
  })

Спасибо за любую помощь, которую вы все можете предоставить.

PS –– Когда я просто нажимаю на вызов .then прямо сейчас, он срабатывает немедленно.Это означает, что мой цикл forEach не блокирует?Я думал, что циклы forEach блокируются.

1 Ответ

0 голосов
/ 29 сентября 2018

Текущий forEach будет работать синхронно и не будет ждать завершения асинхронных операций.Вы должны использовать .map вместо forEach, чтобы вы могли сопоставить каждый элемент его Promise из download.Затем вы можете использовать Promise.all в результирующем массиве, который разрешится после завершения всех download s:

axios.get(`http://federalregister.gov/api/v1/public-inspection-documents.json?conditions%5Bavailable_on%5D=${today}`)
  .then(processResults)
  .catch((err) => {
    console.log("COULD NOT DOWNLOAD FILES: \n", err);
  });
function processResults(res) {
  const downloadPromises = res.data.results.map((item) => (
    download(item.pdf_url).then(data => new Promise((resolve, reject) => {
      writeFile(`${__dirname}/${today}/${item.pdf_file_name}`, data, (err) => {
        if(err) reject(err);
        else resolve(console.log("FILE WRITTEN: ", item.pdf_file_name));
      });
    }))
  ));
  return Promise.all(downloadPromises)
    .then(() => {
      console.log('all done');
    });
}

Если вы хотите по существу блокировать функцию на каждой итерации, вам нужновместо этого используйте функцию async в сочетании с await.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...