jsPDF icon indicating copy to clipboard operation
jsPDF copied to clipboard

jsPdf creating blank pdfs after first pdf generate in loop

Open aryanrajput opened this issue 4 years ago • 13 comments

for (let i=0;i<2;i++){ for (let j=0;j<2;j++){ let doc = new jsPDF("p", "pt", "a4"); doc.html(<p>hi ${i} ${j}</p>, { callback: function (pdf) { pdf.save(i+"_"+j+".pdf"); } }); } }

aryanrajput avatar Sep 03 '21 07:09 aryanrajput

Thanks for reporting this. The reason for the bug is that with your code, the calls to html are executed in parallel due to the asynchronous nature of the html function. If you run the calls strictly after another, it works:

let doc1 = new jsPDF("p", "pt", "a4");
doc1.html(`<p>hi 0</p>`, {
  callback: function(pdf) {
    pdf.save("0.pdf");
    let doc2 = new jsPDF("p", "pt", "a4");
    doc2.html(`<p>hi 1</p>`, {
      callback: function(pdf) {
        pdf.save("1.pdf");
      }
    });
  }
});

However, in theory, different jsPDF instances should be independent of one another and should not share any state. Pull requests to fix this are welcome.

HackbrettXXX avatar Sep 03 '21 08:09 HackbrettXXX

Hi there!

I faced the same problen and just came to realise that an easy workaround to this problem is recursion instead of looping.

const docs = [];
const createPDF = (index) => {
  docs.push(new jsPDF("p", "pt", "a4"));
  docs[index].html(`<p>hi ${index}</p>`, {
    callback: function(pdf) {
      pdf.save(index + ".pdf");
      if (index < 10) {
        createPDF(index + 1);
      }
    }
  });
}
createPDF(0);

Hope this may help...

arnespremberg avatar Sep 11 '21 21:09 arnespremberg

Can I take this issue?

harshilparmar avatar Oct 06 '21 01:10 harshilparmar

@harshilparmar sure, go ahead ;)

HackbrettXXX avatar Oct 06 '21 09:10 HackbrettXXX

@HackbrettXXX So Here I have to fix the behavior of jsPDF instances that should be independent of one another ?

harshilparmar avatar Oct 10 '21 21:10 harshilparmar

@harshilparmar yes.

HackbrettXXX avatar Oct 11 '21 14:10 HackbrettXXX

Thanks for reporting this. The reason for the bug is that with your code, the calls to html are executed in parallel due to the asynchronous nature of the html function. If you run the calls strictly after another, it works:

let doc1 = new jsPDF("p", "pt", "a4");
doc1.html(`<p>hi 0</p>`, {
  callback: function(pdf) {
    pdf.save("0.pdf");
    let doc2 = new jsPDF("p", "pt", "a4");
    doc2.html(`<p>hi 1</p>`, {
      callback: function(pdf) {
        pdf.save("1.pdf");
      }
    });
  }
});

However, in theory, different jsPDF instances should be independent of one another and should not share any state. Pull requests to fix this are welcome.

@HackbrettXXX But here it's working fine right !! please guide me here.

harshilparmar avatar Oct 11 '21 16:10 harshilparmar

@harshilparmar But the original example doesn't work and it should.

HackbrettXXX avatar Oct 12 '21 08:10 HackbrettXXX

@harshilparmar But the original example doesn't work and it should.

But there is only one jsPdf instance right?

harshilparmar avatar Oct 12 '21 11:10 harshilparmar

@harshilparmar But the original example doesn't work and it should.

But there is only one jsPdf instance right?

If a new instance is created in a root that means it's created multiple times thus there are multiple instances.

Without being tied to the maintainers of the project, or knowing the codebase, I could see two approaches to solve this:

One (easier) solution: create a utility function that can be used in place of a loop (so could have a similar syntax to the javascript forEach) that triggers the html rendering recursively as I have shown in my codesnippet above.

Another (cleaner) solution: make sure multiple instances of jsPDF do not share state when called simultaneously. I could imagine that in this specific use case the shared state is related to an HTML canvas or a similar renderer.

I guess @HackbrettXXX has more of an insight and more of an opinion on this :)

arnespremberg avatar Oct 12 '21 11:10 arnespremberg

You're absolutely right @arnespremberg. I'm not exactly sure what state exactly is shared, but finding it out is part of the ticket ;)

HackbrettXXX avatar Oct 13 '21 07:10 HackbrettXXX

i want to work on this issue

kanisshka avatar Oct 01 '22 02:10 kanisshka

Could also be the same as #2899 and is already resolved.

grocholski avatar Oct 06 '23 00:10 grocholski