【问题标题】:Call Function After All Promises在所有承诺之后调用函数
【发布时间】:2019-04-02 19:19:54
【问题描述】:

在所有承诺都解决后,我如何调用函数?我有一个包含三个表格的 HTML 文档。使用 html2canvas(),我通过在 forEach() 循环中迭代它们来创建 JPG:

JavaScript

var elements = document.querySelectorAll( 'table' );
elements = Array.from( elements );

var zip = new JSZip(),
    img = '';

elements.forEach( function( element ) {
    html2canvas( element ).then( canvas => {
        var styleID = element.getAttribute('id');

        img = new Image();
        img.src = canvas.toDataURL( 'image/jpeg' );
        document.body.appendChild( img );

        zip.file( styleID + '.jpg', img.src );
    }).then( generateZip );
});

function generateZip () {
    // Generate the zip file asynchronously
    zip.generateAsync({type:'blob'}).then( function( content ) {
        saveAs( content, 'archive.zip' );
    });
}

问题是 generateZip() 被调用了 3 次,每个循环调用一次。在解决所有承诺之后,如何只调用一次 generateZip() 来创建一个 zip 文件?

【问题讨论】:

标签: javascript jquery promise jszip


【解决方案1】:

在调用generateZip 方法之前,您可以使用Promise#all 了解所有承诺何时完成。使用Promise#all 也很有趣,因为如果一个 html2canvas 失败,整个 Promise 都会失败,并且不会调用 generateZip。

Promise.all() 方法返回一个 Promise,当所有作为可迭代对象传递的承诺都已解决或可迭代对象不包含任何承诺时,该 Promise 将解决。它以第一个拒绝的承诺的原因拒绝。

Promise#all 在then 回调中返回的data 是您的canvass 的数组。

var elements = document.querySelectorAll( 'table' );
elements = Array.from( elements );

var zip = new JSZip(),
    img = '';

function generateZip () {
    // Generate the zip file asynchronously
    zip.generateAsync({type:'blob'}).then( function( content ) {
        saveAs( content, 'archive.zip' );
    });
}

function prepareZip(canvas, element){
        var styleID = element.getAttribute('id');
        img = new Image();
        img.src = canvas.toDataURL( 'image/jpeg' );
        document.body.appendChild( img );
        zip.file( styleID + '.jpg', img.src );
}

Promise.all(elements.map(element=> html2canvas(element)))
.then(data=>{
  data.forEach((canvas, index)=>prepareZip(canvas, elements[index]));
  generateZip();
});

没有箭头函数的解决方案:

var elements = document.querySelectorAll( 'table' );
elements = Array.from( elements );

var zip = new JSZip(),
    img = '';

function generateZip () {
    // Generate the zip file asynchronously
    zip.generateAsync({type:'blob'}).then( function( content ) {
        saveAs( content, 'archive.zip' );
    });
}

function prepareZip(canvas, element){
        var styleID = element.getAttribute('id');
        img = new Image();
        img.src = canvas.toDataURL( 'image/jpeg' );
        document.body.appendChild( img );
        zip.file( styleID + '.jpg', img.src );
}

Promise.all(elements.map(function(element){ return html2canvas(element); }))
.then(function(data){
  data.forEach(function(canvas, index){
    prepareZip(canvas, elements[index])
  });
  generateZip();
});

【讨论】:

  • 如何访问 prepareZip() 中元素的值?我得到:ReferenceError:元素未定义。
  • 您的代码有效,但箭头 => 函数让我(新手)感到困惑。您可以使用常规函数调用而不是箭头 => 函数来编写代码吗?它对我来说更具可读性。谢谢!
  • @kemicoa 太棒了,你是摇滚明星。最好的!非常感谢。是的,我必须了解更多关于箭头函数的知识才能适应它们。顺便说一句,您签名中的引用,Tron:Legacy。好电影! B-)
猜你喜欢
  • 2017-08-12
  • 1970-01-01
  • 2022-01-08
  • 2016-01-10
  • 2023-03-28
  • 2014-02-18
  • 2020-04-22
  • 2016-12-06
  • 2018-06-27
相关资源
最近更新 更多