在所有承诺之后调用函数

Call Function After All Promises

如何在所有承诺都已解决后调用函数?我有一个包含三个表的 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() 被调用了三次,每个循环调用一次。在所有承诺都已解决后,如何仅调用一次 generateZip() 来创建一个 zip 文件?

您可以使用 Promise#all to know when all the promises have completed before calling generateZip method. It is also interesting to use Promise#all 因为如果一个 html2canvas 失败,整个 Promise 将失败并且不会调用 generateZip。

The Promise.all() method returns a single Promise that resolves when all of the promises passed as an iterable have resolved or when the iterable contains no promises. It rejects with the reason of the first promise that rejects.

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

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();
});