Javascript 如何在每个选择器的JQuery之后添加回调?

Javascript 如何在每个选择器的JQuery之后添加回调?,javascript,jquery,asynchronous,callback,jspdf,Javascript,Jquery,Asynchronous,Callback,Jspdf,我正在尝试使用jsPDF将html转换为pdf。我的代码是: var doc = new jsPDF(); $(document).ready(function() { $("#runpdf").click(function(event) { $(".page").each(function(){ html2canvas($(this), { logging:true, profile

我正在尝试使用jsPDF将html转换为pdf。我的代码是:

var doc = new jsPDF();
$(document).ready(function() 
{
    $("#runpdf").click(function(event) 
    {
    $(".page").each(function(){


        html2canvas($(this),
        {
            logging:true,
            profile:true,
            allowTaint:true,
            letterRendering: true,
            onrendered:function(canvas)
            {
                var imageData = canvas.toDataURL("image/jpeg");     
                doc.addImage(imageData, 'JPEG', 0, 0, 200, 200);

            }
        });

    });
    doc.save('test.pdf');
    });
});

这意味着要呈现一个带有图像的pdf,但是它会给出一个空白页面。显然,这是因为
onrendered
是异步的,因此
doc.save
在完成之前执行,在
onrendered
函数向其添加图像之前提供一个空白页。那么,我如何才能在each函数或类似函数上编写回调函数,以确保
doc.save
在遍历
$(“.page”)
的每个实例之前不会执行?
谢谢

您必须跟踪最后一次完成的时间,然后调用
doc.save()
。下面是一个实现,我只是将
doc.save()
放在
onrendered
函数中。如果愿意,可以在那里调用回调,并在回调中使用
doc.save()
。以下是总体思路:

var doc = new jsPDF();
$(document).ready(function () {
    $("#runpdf").click(function (event) {
        var pages = $(".page");
        // initialize count of how many left to go
        var remaining = pages.length;
        pages.each(function () {
            html2canvas($(this), {
                logging: true,
                profile: true,
                allowTaint: true,
                letterRendering: true,
                onrendered: function (canvas) {
                    var imageData = canvas.toDataURL("image/jpeg");
                    doc.addImage(imageData, 'JPEG', 0, 0, 200, 200);
                    --remaining;
                    // if all are done, the call save
                    if (remaining === 0) {
                        doc.save('test.pdf');
                    }
                }
            });

        });

    });
});

此外,如果您再次单击
#runpdf
按钮,我怀疑这不起作用。您可能希望将
doc
的初始化移动到单击处理程序中。

您必须跟踪上一次初始化的完成时间,然后调用
doc.save()
。下面是一个实现,我只是将
doc.save()
放在
onrendered
函数中。如果愿意,可以在那里调用回调,并在回调中使用
doc.save()
。以下是总体思路:

var doc = new jsPDF();
$(document).ready(function () {
    $("#runpdf").click(function (event) {
        var pages = $(".page");
        // initialize count of how many left to go
        var remaining = pages.length;
        pages.each(function () {
            html2canvas($(this), {
                logging: true,
                profile: true,
                allowTaint: true,
                letterRendering: true,
                onrendered: function (canvas) {
                    var imageData = canvas.toDataURL("image/jpeg");
                    doc.addImage(imageData, 'JPEG', 0, 0, 200, 200);
                    --remaining;
                    // if all are done, the call save
                    if (remaining === 0) {
                        doc.save('test.pdf');
                    }
                }
            });

        });

    });
});

此外,如果您再次单击
#runpdf
按钮,我怀疑这不起作用。您可能希望将
doc
的初始化移到click处理程序中。

这是jQuery实现承诺的完美用例

简而言之,您可以为每个
html2canvas
操作创建一个延迟对象,然后在
onrendered
回调调用
Deferred.resolve()
中。然后在循环结束后,使用所有延迟对象作为参数调用
$。解决所有延迟后,
$。当
被解决时,您作为对
$的回调而提供的函数将被执行。然后
,其中包含您对
doc.save
的调用

我还没有测试过这段代码,但它应该或多或少是正确的(我已经用
/标记了添加的代码)★★★):


这是jQuery实现承诺的完美用例

简而言之,您可以为每个
html2canvas
操作创建一个延迟对象,然后在
onrendered
回调调用
Deferred.resolve()
中。然后在循环结束后,使用所有延迟对象作为参数调用
$。解决所有延迟后,
$。当
被解决时,您作为对
$的回调而提供的函数将被执行。然后
,其中包含您对
doc.save
的调用

我还没有测试过这段代码,但它应该或多或少是正确的(我已经用
/标记了添加的代码)★★★):


来自同一海报的相关问题:来自同一海报的相关问题:是!非常感谢你!这正是我需要的。谢谢。@yodofizzy请接受另一个答案,使用jQuery
$。延迟
确实是最好的解决方案,您将在这个过程中学习到一种非常强大的技术。是的!非常感谢你!这正是我需要的。谢谢哈哈,我对所有这些javascript、jquery和回调(虽然我熟悉java和基本编程)之类的东西都很陌生,所以我尝试使用这些东西,假设答案隐藏在那里的某个地方,搜索旧论坛线程、教程和文档,现在,当我意识到我所需要的东西可以用一个简单的计数器和一个if语句轻松地完成时,我真的感到很傻。再次感谢。@Alnitak-当底层操作尚未为您创建承诺时,我当然不清楚基于承诺的解决方案是否更干净。这是一种涉及更多代码的不同技术。毫无疑问,尊重是一个强有力的概念,但并不总是最简单的做事方式。我一直在使用它们,特别是当底层操作已经返回承诺(比如jqueryajax)时。但是,在这种情况下,我不能诚实地说,创建一堆延期更简单。事实上,它们不一定更简单,但它们肯定更干净。在另一个答案中比较它是如何从<代码>的内部去掉<代码> doc.Save调用。每个< /代码>循环,保留OP的原始代码结构,即使发生在中间的东西都是异步的。是的!非常感谢你!这正是我需要的。谢谢。@yodofizzy请接受另一个答案,使用jQuery
$。延迟
确实是最好的解决方案,您将在这个过程中学习到一种非常强大的技术。是的!非常感谢你!这正是我需要的。谢谢哈哈,我对所有这些javascript、jquery和回调(虽然我熟悉java和基本编程)之类的东西都很陌生,所以我尝试使用这些东西,假设答案隐藏在那里的某个地方,搜索旧论坛线程、教程和文档,现在,当我意识到我所需要的东西可以用一个简单的计数器和一个if语句轻松地完成时,我真的感到很傻。再次感谢。@Alnitak-当底层操作尚未为您创建承诺时,我当然不清楚基于承诺的解决方案是否更干净。这是一种涉及更多代码的不同技术。毫无疑问,尊重是一个强有力的概念,但并不总是最简单的做事方式。我一直在使用它们,特别是当底层操作已经返回承诺(比如jqueryajax)时。但是,在这种情况下,我不能诚实地说,创建一堆延期更简单。事实上,它们是n