javascript - 循环、异步/等待、createWriteStream 和延迟

标签 javascript node.js

我正在尝试从 URL 下载 pdf 文件并将其保存到我的本地磁盘。问题是我需要一次下载一个文件,中间有一个时间延迟(延迟应该约为 1 秒)。也就是说:下载一个文件后,脚本应等待一整秒才能下载下一个文件。

  1. 等待文件下载
  2. 等待文件保存到磁盘
  3. 等一下
  4. 再次开始循环

代码:

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/

相关文章:

node.js - 无法将GRPC微服务与客户端连接-k8s上的Nest JS Node

mysql - 从多个表中提取 Sequelize 信息

node.js - 在 bash 中将数据作为数组插入文件

javascript - 切换 CSS 类对元素没有影响

javascript - 当必须从空数据重绘时,FullCalendar 为空

javascript - 将另一个媒体观点添加到我的 javascript

node.js - Node : Hit endpoint that returns a CSV file and send the contents to client

Node.js 未按预期输出

javascript - 如何使用输入附加验证表单字段

javascript - jquery 两个 div 使用 'hover' 事件