【问题标题】:Refactoring Complicated Nested Node.js Function重构复杂的嵌套 Node.js 函数
【发布时间】:2018-09-28 23:47:21
【问题描述】:

我在下面有以下代码的 sn-p。它目前有效,但我希望对其进行一些优化/重构。

基本上,它会获取 JSON 数据,从响应中提取多个 PDF 的 URL,然后将这些 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);
  })

感谢大家提供的任何帮助。

附: –– 当我现在简单地拨打.then 电话时,它会立即触发。这意味着我的 forEach 循环是非阻塞的?我认为 forEach 循环被阻塞了。

【问题讨论】:

    标签: javascript node.js asynchronous promise refactoring


    【解决方案1】:

    当前forEach同步运行,并且不会等待异步操作完成。您应该使用.map 而不是forEach,这样您就可以将每个项目从download 映射到它的Promise。然后,您可以在结果数组上使用Promise.all,这将在所有downloads 完成后解析:

    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 结合使用。

    【讨论】:

    • 嗯,我理解这个想法,但是当我使用你的代码时,“全部完成”块并没有为我触发。文件正在下载。我错过了什么吗?
    • 应该工作,请注意download 产生的Promise 链在.map 中隐式返回 - 你复制了它,对吗? (括号,不是大括号)
    • 您的解决方案似乎没有问题,但由于某种原因,脚本始终无法下载所有资源...有 126 个 pdf 链接,这些链接始终由对第一个链接的请求。但是下载器功能无法下载所有这些。这是我的 git:github.com/KingOfCramers/federal-register-searcher
    • 如果download函数正常的话,如果有问题应该会报错,也就是说错误会在上面的catch可见,对吧?
    • 可能是连接问题?它只下载了 126 个文件中的 84 个……如果你下载了 git,你会遇到同样的问题吗?如果你能帮忙,请告诉我,谢谢
    猜你喜欢
    • 2018-05-15
    • 2023-04-03
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多