jsPDF + html2canvas aw snap на chrome, а не на firefox - PullRequest
0 голосов
/ 04 июня 2018

Я пишу генератор PDF с помощью html2canvas + jsPDF.Я использую рекурсивный метод для этого.Когда я запускаю его на Chrome, он делает «Aw snap!»исключение о 25-й итерации.На Mozilla я могу пройти более 30, и он не рухнет.Я не понимаю почему.Вот мой код:

function pdfMe(){
        var pdf=new jsPDF('l');
        var slides=document.getElementById("diapoStock").children; //return some divs
        var firstSlide=slides[0].id;
        pdfSlide(firstSlide,firstSlide,pdf);
    }
    //PDF recursive
    function pdfSlide(id,idFirst,pdf){
        document.getElementById("pdfOutput").innerHTML="";   //empty the output
        var next=nextElementOf(id.substr(0,id.length-3)+"Div");    //next div to PDF
        showMe(id.substr(0,id.length-3));                //Show the div to PDF in 'central'
        html2canvas(document.getElementById("central",{async:true})).then(function (canvas) {
            document.getElementById("pdfOutput").appendChild(canvas);   //div to PDF shown
            var img=canvas.toDataURL("image/png");
            pdf.addImage(img, 'PNG', 0, 0, 297, 210);    //div added to PDF
            if(next===idFirst){                          //if end of divs
                endPDF(pdf);
            }
            else{
                pdf.addPage();
                pdfSlide(next,idFirst,pdf);             //to next div
            }
        });
    }
    //Print
    function endPDF(pdf){
        pdf.save('{{ propale.titre }}.pdf');
    }

Я не знаю, связано ли это с разницей в размере кэша.Я напечатал это с console.log(window.performance.memory);, но это дало мне то же самое для 10 или 30 итераций.

Это из-за моего рекурсивного метода?Использует ли он слишком много памяти?

Надеюсь, это понятно

1 Ответ

0 голосов
/ 04 июня 2018

Несколько вещей, которые я заметил: Ваша переменная 'firstSlide' всегда перезаписывалась функцией pdfMe() при каждом ее вызове.Это никогда не переходило на ветку if(next === idFirst).Это также привело к тому, что браузер снова и снова пытался асинхронно переходить к pdfSlide(), который сломал браузер.

Вы передали одну и ту же переменную firstSlide дважды в функцию pdfSlide(), но это ничего не сломало.не нужно.

Я считаю, что приведенное выше сравнение является ключом к повышению вашей производительности.Я просто добавил флаг «first», чтобы показать вам, как я подхожу к сохранению самого первого элемента, а затем запускаю итерацию.Когда вы дойдете до последнего (я не смог определить его по вашему коду), попробуйте придумать другой оператор if() для выхода из рекурсивной функции.

Я знаю, что это не будет копией-пастой ответ, но, надеюсь, направит вас в правильном направлении.

var first = true;
var firstID = "";

function pdfMe(){
    var pdf = new jsPDF('l');
    var slides = document.getElementById("diapoStock").children;
    if(first) firstID = slides[0].id; // creating this 'first' flag not to overwrite with every iteration
    first = false;
    pdfSlide(slides[0].id,firstID,pdf); // you were passing the same argument twice to the pdfSlide function. Removed one of those
};

// Added these options from the html2canvas documentation
var options = {
  async: true,
  allowTaint: false,
  imageTimeout: 0
}
function pdfSlide(id,firstID,pdf){
    document.getElementById("pdfOutput").innerHTML="";
    var next = nextElementOf(id.substr(0,id.length-3)+"div"); // this needs to be set differently
    showMe(id.substr(0,id.length-3));
    
    html2canvas(document.getElementById("central",options)).then(function(canvas){
        document.getElementById("pdfOutput").appendChild(canvas);
        var img = canvas.toDataURL("image/png");
        pdf.addImage(img, 'PNG', 0, 0, 297, 210);
        if(next.id === firstID){                          // <-- this condition never happened and because of asynchronous behaviour browser tries to load the else->recursive again and again
            endPDF(pdf);
        }
        else{
            pdf.addPage();
            pdfSlide(next,idFirst,pdf);
        }
    });
}
//Print
function endPDF(pdf){
    pdf.save('{{ propale.titre }}.pdf');
}
...