Функция вызова после всех обещаний - PullRequest
1 голос
/ 02 апреля 2019

Как я могу вызвать функцию после того, как все обещания будут выполнены?У меня есть HTML-документ с тремя таблицами.Используя html2canvas (), я создаю JPG, перебирая их в цикле forEach ():

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-файл?

1 Ответ

2 голосов
/ 02 апреля 2019

Вы можете использовать Promise # all , чтобы узнать, когда все обещания были выполнены до вызова метода generateZip. Также интересно использовать Promise # all , потому что при сбое одного html2canvas произойдет сбой всего Promise и не будет вызван generateZip.

Метод Promise.all () возвращает одно Обещание, которое разрешается, когда все обещания, переданные как итеративные, разрешены или когда итерация не содержит обещаний. Он отклоняет причину первого обещания, которое отклоняет.

data, возвращаемый Promise #, все в обратном вызове then - это массив ваших canvas s.

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