Estoy tratando de descargar archivos pdf desde una URL y guardarlos en mi disco local. El problema es que necesito que cada archivo se descargue uno a la vez con un retraso de tiempo en el medio (el retraso debe ser de aproximadamente 1 segundo). Es decir: después de descargar un archivo, el script debe esperar un segundo completo antes de descargar el siguiente archivo).
El código:
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(); })();Lo que quiero que los registros muestren esto:
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***En cambio, los registros muestran esto:
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*** Y la demora tampoco funciona (todos los archivos se descargan a la vez) ya que i in await wait(1000 * i) siempre es 0;
Cualquier ayuda es apreciada.
El async IIFE es tu problema. Ese IIFE devuelve una promesa con la que no está haciendo nada, por lo que el ciclo for sigue ejecutándose porque nada está esperando esa promesa que devuelve el IIFE.
Sería mejor arreglar su código simplemente eliminando ambos IIFE y eliminando el new Promise() completamente de esta manera:
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); }); Y tenga en cuenta que también agregué un controlador de errores para writeStream .
Cuando sustituyo algunas URL reales y ejecuto esto en mi sistema, obtengo este resultado y hay una pausa notable entre las descargas:
File 0 Download Begun ----- DOWNLOAD COMPLETE ----- File 1 Download Begun ----- DOWNLOAD COMPLETE ----- File 2 Download Begun ----- DOWNLOAD COMPLETE ----- done Los IIFE async pueden causarle problemas muy fácilmente. Devuelven una promesa (TODAS las funciones async devuelven una promesa), por lo que si no está prestando atención a esa promesa, nadie esperará a que terminen antes de continuar con su código. Nunca uso un IIFE asíncrono ya que siempre ha habido (para mí) una forma más limpia de escribir mi código.
Además, ¿por qué te detienes entre iteraciones de bucle? Se siente como si fuera un intento de piratear/arreglar algún problema de simultaneidad que ya no debería estar allí o debería solucionarse de una manera más fundamental.