Reputation: 79
I am trying to download files from a website and would like to pause the code for 1s between each request using setTimeout.
I have a stockFile function that loops through an array of urls (path is where I stock the file on my disk). Here is my code (version A):
async function stockFiles(urls, path) {
_.map(urls, async (elem) => {
await timeOut(1000);
const writableStream = await _createWriteStream(path);
await _getFile(elem, writableStream);
});
}
function timeOut(ms) {
return new Promise((fulfill) => {
setTimeout(fulfill, ms);
});
}
Edit: Version B:
async function stockFiles(urls, path) {
_.map(urls, async (elem) => {
const writableStream = await _createWriteStream(path);
await _getFile(elem, writableStream);
await timeOut(1000);
});
}
function timeOut(ms) {
return new Promise((fulfill) => {
setTimeout(fulfill, ms);
});
}
THE PROBLEM: When I call stockFiles (version A), it does pause before making the request, but then it seems like I receive all files at the same time on my disk. What I really want is my code to pause between EACH request, so there is a delay between each file reception.
Edit: When I call stockFiles (version B), it doesn't pause execution at all, and I receive all the files at the same time.
/**************** helpers functions **************/
function _createWriteStream(path) {
return new Promise((fulfill, reject) => {
fs.createWriteStream(path, (err, data) => {
if (err) {
reject(err);
}
fulfill(data);
});
});
}
// I use superagent package to make the request
async function _getFile(url, writableStream) {
await request
.get(url)
.buffer(true).parse(request.parse.image)
.pipe(writableStream);
}
Upvotes: 2
Views: 2723
Reputation: 3678
The problem is that you are starting all the requests at the same time, then they are all waiting 1000 ms from that time, and then they are all executing. It sounds like you already understand this. What you need to do is queue them up so that each one starts only after the previous one finishes.
Try changing your stockFiles function to something more like this:
async function stockFiles(urls, path) {
for (let url of urls) {
const writableStream = await _createWriteStream(path);
await _getFile(elem, writableStream);
await timeOut(1000);
}
}
Here is some full example code. I have tested it and observed that the loop only runs one iteration per second (as can be seen by observing the console.logs).
function timeOut(ms) {
return new Promise((fulfill) => {
setTimeout(fulfill, ms);
});
}
async function stockFiles(urls, path) {
for (let url of urls) {
console.log(url);
await timeOut(1000);
}
}
let urls = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
stockFiles(urls);
Upvotes: 1