suzee
suzee

Reputation: 603

Check if a promise finished in Javascript?

I am using PDF.js to extract text content from a PDF which I will use next for some more processing, For this,

var complete=0;
var full_text="";
var PDF_render = PDFJS.getDocument("x.pdf").then(function(pdf) {
    var page_text = {};
    for (i = 1; i <= pdf.numPages; i++){
        pdf.getPage(i).then( function(page){
           var n = page.pageNumber;
            page.getTextContent().then( function(textContent){
                var page_text_part = "";
                textContent.items.forEach(function (textItem){
                    page_text_part += textItem.str;
                    page_text_part += " ";
                    });
                page_text[n] =  page_text_part + "\n\n";
                ++complete;
                if (complete == pdf.numPages){
                 for( var j = 1; j <= pdf.numPages; j++)
                    full_text += page_text[j];
                }
              });
            });
        }
    });

The issue is that PDF.js returns promises and they are executed asynchronously, however I need to perform some post processing on the returned text. For this I need to wait for the promises to fully execute and only then move on. How does one achieve this? Please help.

Upvotes: 1

Views: 5952

Answers (3)

Juozas Kontvainis
Juozas Kontvainis

Reputation: 9597

Unfortunately this question asks one thing in title (how to check if Promise finished), and another in the body (how to continue once Promise is finished). Google points to this when searching for how to check if Promise is finished, so I'm answering the question in the title.

To check if a promise if is finished, you can use Promise.race - it will not wait for pending promise if given non-promise value, e.g.

const statusOrValue = await Promise.race([myPromise, 'pending']);
if (statusOrValue === 'pending') {
    // Not yet finished
}

Note that this method gives the result asynchronously - await is necessary to check if promise is finished. I don't know if there is a reliable way to check whether promise is completed synchronously.

Upvotes: 8

Bergi
Bergi

Reputation: 664886

You can use Promise.all to wait for multiple promises to have resolved.

In your case, the code should look like

PDFJS.getDocument("x.pdf").then(function(pdf) {
    var pages = [];
    for (var i = 1; i <= pdf.numPages; i++) {
        pages.push(pdf.getPage(i).then(function(page) {
            return page.getTextContent();
        }).then(function(textContent) {
            return textContent.items.map(function(textItem){
                return textItem.str;
            }).join(" ") + " \n\n";
        });
    return Promise.all(promises);
}).then(function(page_texts) {
    var full_text = page_texts.join("");
    // now do something with the result
});

Upvotes: 3

Benjamin Gruenbaum
Benjamin Gruenbaum

Reputation: 276386

We can use a much more direct approach, no need for counters etc.

Two things - promises chain, and waiting for multiple promises is done with Promise.all:

var pdf = PDFJS.getDocument("x.pdf");

pdf.then(function(pdf) { // wait for the PDF to load
    var pages = [];
    for (i = 1; i <= pdf.numPages; i++){ // for each pages
        pages.push(pdf.getPage(i).then(function(page){ // push the promise
            return page.getTextContent();
        }).then(function(textContent){
            var page_text_part = "";
            textContent.items.forEach(function (textItem){
                    page_text_part += textItem.str + " ";
            });
            return page_text_part + "\n\n"; // you can use return values
        }));
    }
    return Promise.all(pages); // wait for all of them to be done
}).then(function(results){
     // you can access all the results here
     // containing all pages
});

Upvotes: 3

Related Questions