Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

jsPDF show loading while processing. Promise does not wait

I'm using JSPDF and autotables plugin for PDF reports. While the PDF generation is happening I'm trying to show a loading image. Unfortunately, the loading is ignored even when trying with async().

function createPDF(){
  return new Promise(resolve => {
   var doc = new jsPDF();
    doc.autoTable({
        body: [
            ['Elmo', 'Hello'],
            ['Bert', 'The Muppet Show.']
        ]
    });
    
    // mimik time for processing
    setTimeout(function(){
      console.log('wait time for loading image')
    }, 8000);

    doc.save('table.pdf');
    resolve('resolved');

    });
}

async function asyncPDF() {
  document.getElementsByClassName('img__loading')[0].style.display = 'block';
  var result = await createPDF();
  document.getElementsByClassName('img__loading')[0].style.display = 'none';
}

document.getElementById('save').addEventListener("click", asyncPDF );
.img__loading{
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.1.1/jspdf.plugin.autotable.min.js"></script>


<button id="save">save</button>
<img src="https://ui-ex.com/images/transparent-background-loading.gif" class="img__loading">

The question is why is the loading image not showing up? And why does it start working when wrapping the save() and resolve() inside the timeout?

  setTimeout(function(){
      doc.save('table.pdf');
      resolve('resolved');
  }, 8000);
like image 431
Anatol Avatar asked Oct 19 '25 00:10

Anatol


2 Answers

Use promise.then instead of async .And for testing your setTimeout was wrong place.You need to wrap with resolve .While on click your async function trigger all the inner calls.so loading as been immediately disappear after present that why wrap with in then function.then only detect the event finished from promise

function createPDF(){
  return new Promise(resolve => {
   var doc = new jsPDF();
    doc.autoTable({
        body: [
            ['Elmo', 'Hello'],
            ['Bert', 'The Muppet Show.']
        ]
    });

      console.log('wait time for loading image')


    doc.save('table.pdf');
    setTimeout(()=>{
    resolve('resolved');
    },3000)

    });
}

function asyncPDF() {
  document.getElementsByClassName('img__loading')[0].style.display = 'block';
  createPDF().then(()=>{
  document.getElementsByClassName('img__loading')[0].style.display = 'none'})
}

document.getElementById('save').addEventListener("click", asyncPDF );
.img__loading{
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.5.3/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/3.1.1/jspdf.plugin.autotable.min.js"></script>


<button id="save">save</button>
<img src="https://ui-ex.com/images/transparent-background-loading.gif" class="img__loading">
like image 181
prasanth Avatar answered Oct 20 '25 13:10

prasanth


The right answer is:

doc.save('export.pdf', { returnPromise: true }).then(() => {
  // Code will be executed after save
});

Use a setTimeout to fake a promise is a bad practice.

like image 35
brydar Avatar answered Oct 20 '25 15:10

brydar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!