我在下面有以下代码段。目前可以使用,但是我希望对其进行一些优化/重构。
基本上,它会获取JSON数据,从响应中提取多个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);
})
感谢大家提供的任何帮助。
P.S。 -当我现在只需接通.then
呼叫时,它将立即触发。这意味着我的forEach循环是非阻塞的吗?我以为forEach循环正在阻塞。
答案 0 :(得分:2)
当前的forEach
将同步运行,并且不会等待异步操作完成。您应该使用.map
而不是forEach
,以便可以将每个项目从Promise
映射到其download
。然后,您可以在结果数组上使用Promise.all
,一旦完成所有download
的解析,即可解析:
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
结合使用。