Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to force resolve a promise after certain duration in node.js? [duplicate]

I am trying to download a large number images from their url(s) and then creating a PDF file out of them in Node.js. I'm using the image-downloader module to download the images in a promise chain and then once all promises are resolved, using another module, images-to-pdf, to trigger the creation of the pdf.
The problem is that most of the promises get resolved immediately in around 5-6 seconds, but there are a few images that are taking quite a bit of time to download. I'd like to force trigger the PDF creation after a certain interval of waiting. Can that be done?
Here is the code

var promises = data.map(function(element){
    return download.image(element)
    .then( ({filename}) => {
        console.log("Saved to ",filename);
        return filename;
    })
});

Promise.all(promises).then(function (data){
    var fileName = url.slice(url.indexOf("files")+7, url.length-1).replace("/","_")+".pdf";
    data.forEach(
        (element) => {console.log(element);
    });
    imagesToPdf(data, fileName)
    .then(console.log(" PDF creation done."));
})
.catch ((error) => {
    console.error(error);
});

The data getting passed in data.map is a JSON object of the following nature -

[
  { 
    url:"https://path//to//image//001.jpg",
    dest:"local//path//to//image//001.jpg"
  },
  { 
    url:"https://path//to//image//002.jpg",
    dest:"local//path//to//image//002.jpg"
  },
  { 
    url:"https://path//to//image//003.jpg",
    dest:"local//path//to//image//003.jpg"
  },
  ...
}]
like image 783
srdg Avatar asked Oct 28 '25 15:10

srdg


1 Answers

You can use Promise.race() to add a timeout to each images promise and if you're going to resolve it, then you need to resolve it with some sentinel value (I use null here in this example) that you can test for so you know to skip it when processing the results.

function timeout(t, element) {
    return new Promise(resolve => {
        // resolve this promise with null
        setTimeout(resolve, t, element);
    });
}

var promises = data.map(function(element) {
    const maxTimeToWait = 6000;
    return Promise.race([download.image(element).then(({ filename }) => {
        console.log("Saved to ", filename);
        return filename;
    }), timeout(maxTimeToWait)]);
});

Then, in your code that processes the results from Promise.all(), you need to check for null and skip those because those are the ones that timed out.

like image 82
jfriend00 Avatar answered Oct 30 '25 07:10

jfriend00