jsPDF 在处理时显示加载。承诺不等待

jsPDF show loading while processing. Promise does not wait

我正在使用 JSPDF 和 PDF 报告的自动表格插件。在生成 PDF 时,我正在尝试显示加载图像。不幸的是,即使在尝试使用 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">

请问为什么加载图片不显示?为什么在超时内包装 save() 和 resolve() 时它开始工作?

  setTimeout(function(){
      doc.save('table.pdf');
      resolve('resolved');
  }, 8000);

我认为装载机没有足够的时间。你的 pdf 相关的东西做得太快了,promise resolves 和 loader hides,所以它的工作原理如下:

// show loader
// creating pdf took several milliseconds
// hide loader

当您使用 setTimeout 时,您将 promise 解析推迟了 8 秒。

setTimeout(function(){
      doc.save('table.pdf');
      resolve('resolved'); // resolve is also postponed
  }, 8000);

因此加载程序显示了 8 秒。用户有足够的时间看到它。

此外,只要您同时操作 DOM,最好使用 setTimeout 从一些繁重的操作中卸载主线程。但是,使用 WebWorkers 将是最好的解决方案

您已将其包装到 Promise 中,这很好,但它立即得到解决,只是因为没有它应该等待的地方。 setTimeout 有效,因为您在一定时间后调用 resolve

jsPDF 站点中您可以找到 API 的 save 方法: http://raw.githack.com/MrRio/jsPDF/master/docs/jsPDF.html#save

您可能感兴趣的选项是returnPromise

这就是应该做的工作:

await doc.save('table.pdf', {returnPromise: true});

不幸的是,我不熟悉 jsPDF 库和 autotable 插件,所以请原谅任何与库相关的错误。

使用 promise.then 而不是异步。为了测试你的 setTimeout 是错误的 place.You 需要用 resolve 包装。点击你的异步函数时触发所有内部 calls.so loading as been immediately disappear after present that why wrap with in then function.then 只检测从 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">