我正在尝试从 URL 下载 pdf 文件并将其保存到我的本地磁盘。问题是我需要一次下载一个文件,中间有一个时间延迟(延迟应该约为 1 秒)。也就是说:下载一个文件后,脚本应等待一整秒才能下载下一个文件。
- 等待文件下载
- 等待文件保存到磁盘
- 等一下
- 再次开始循环
代码:
const fs = require('fs');
const fetch = require('node-fetch');
const arrayOfURL = ['www.link.com/file1', 'www.link.com/file2', 'www.link.com/file3'];
const wait = waitTime => new Promise(resolve => setTimeout(resolve, waitTime));
(async() => {
async function downloadAllFiles() {
return new Promise((resolve, reject) => {
(async() => {
for (let i = 0; i < arrayOfURL.length; i++) {
console.log(`File ${i} Download Begun`);
const response = await fetch(arrayOfURL[i]);
const writeStream = fs.createWriteStream(i + '.pdf');
response.body.pipe(writeStream);
async function write() {
return new Promise((resolve, reject) => {
writeStream.on('finish', function () {
resolve('complete');
});
});
}
await write();
console.log(`----- DOWNLOAD COMPLETE -----`);
await wait(1000 * i);
if (i === 2) {
resolve('complete');
}
}
})();
});
}
await downloadAllFiles();
})();
我想要日志显示的是:
console.log(`File 0 Download Begun`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
***Wait 1 second***
console.log(`File 1 Download Begun`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
***Wait 1 second***
console.log(`File 2 Download Begun`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
***Wait 1 second***
日志显示的是这样的:
console.log(`File 0 Download Begun`);
console.log(`File 1 Download Begun`);
console.log(`File 2 Download Begun`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
console.log(`File Saved Locally`);
console.log(`----- DOWNLOAD COMPLETE -----`);
***Downloaded at the same time***
延迟也不起作用(所有文件都会立即下载),因为 await wait(1000 * i)
中的 i
始终为 0;
感谢任何帮助。
最佳答案
async
IIFE 是你的问题。该 IIFE 返回一个您不执行任何操作的 Promise,因此 for
循环会继续运行,因为没有任何东西等待 IIFE 返回的 Promise。
最好通过删除两个 IIFE 并完全删除 new Promise()
包装器来修复代码,如下所示:
const fs = require('fs');
const fetch = require('node-fetch');
const arrayOfURL = ['www.link.com/file1', 'www.link.com/file2', 'www.link.com/file3'];
const wait = waitTime => new Promise(resolve => setTimeout(resolve, waitTime));
async function downloadAllFiles() {
for (let i = 0; i < arrayOfURL.length; i++) {
console.log(`File ${i} Download Begun`);
const response = await fetch(arrayOfURL[i]);
const writeStream = fs.createWriteStream(i + '.pdf');
response.body.pipe(writeStream);
async function write() {
return new Promise((resolve, reject) => {
writeStream.on('finish', function() {
resolve('complete');
});
writeStream.on('error', reject);
});
}
await write();
console.log(`----- DOWNLOAD COMPLETE -----`);
await wait(1000);
}
}
downloadAllFiles().then(() => {
console.log("done");
}).catch(err => {
console.log(err);
});
请注意,我还为 writeStream
添加了一个错误处理程序。
当我替换一些真实的 URL 并在我的系统上运行它时,我得到以下输出,并且下载之间有明显的暂停:
File 0 Download Begun
----- DOWNLOAD COMPLETE -----
File 1 Download Begun
----- DOWNLOAD COMPLETE -----
File 2 Download Begun
----- DOWNLOAD COMPLETE -----
done
async
IIFE 很容易给您带来麻烦。它们返回一个 promise (所有async
函数都返回一个 promise ),因此如果您不注意该 promise ,那么没有人会等待它们完成后再继续您的代码。我从不使用异步 IIFE,因为(对我来说)一直有一种更简洁的方式来编写我的代码。
另外,为什么要在循环迭代之间暂停。这感觉就像是试图破解/修复一些并发问题,这些问题不应该再存在,或者应该以更根本的方式修复。
关于javascript - 循环、异步/等待、createWriteStream 和延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70536958/