点击事件的JQuery .done

tob*_*new 7 javascript jquery

我不是一个javascript开发人员,所以请耐心等待...

我需要在jQuery click事件完成后执行重定向.这是我的,但我不能申请.done.click.将整个事物包装起来$.when并不起作用......

$("#printpng").click(function(){
            $('#tool_docprops').click();
            $('#tool_docprops_save').click();
            $('#tool_export').click()
        }).done(function(){
                window.location.href = "<?php echo $base_url ?>/sign/print"
        });
Run Code Online (Sandbox Code Playgroud)

有没有人有更好的解决方案?

谢谢

Gon*_*ing 12

假设每次单击都触发了一个Ajax调用(你为什么会遇到这个问题),你可以简单地等待任何/所有Ajax请求完成:

$(document).ajaxStop(function () {
     window.location.href = "<?php echo $base_url ?>/sign/print"
  });
Run Code Online (Sandbox Code Playgroud)

如果需要,您还可以在更改URL之前添加超时,以防在Ajax加载后进行其他处理.如果它不是Ajax问题请澄清,我将调整(或删除)这个答案.

完整版(在Ajax等待之后延迟1秒)可能看起来像:

$("#printpng").click(function(){
    $('#tool_docprops').click();
    $('#tool_docprops_save').click();
    $('#tool_export').click();
    $(document).ajaxStop(function () {
        setTimeout(function(){
             window.location.href = "<?php echo $base_url ?>/sign/print"
        }, 1000);
    });
});
Run Code Online (Sandbox Code Playgroud)

正如所承诺的[sic]使用promises更好的解决方案

由于从未提供完整的代码,假设有多个ajax调用,解决方案就是猜测.

一般的解决方案是不触发点击事件,而是以承诺友好的方式简单地为每次点击调用相关代码.

假设每个单击处理程序都有一个专用函数,只需让每个函数返回一个promise:

例如

 function loadPropsViaAjax(){
     // simply return the ajax call as $.ajax returns a promise
     return $.ajax({parameters here});
 }

 function saveDocPropsViaAjax(){
     // simply return the ajax call as $.ajax returns a promise
     return $.ajax({parameters here});
 }

 function waitForImageToload(){
     // create a deferred object
     var def = $.Deferred();

     // When the image eventually loads, resolve the promise
     $('#someimageselector').on('load', function(){
        def.resolve();
     });

     // Return the promise immediately
     return def.promise();
 }
Run Code Online (Sandbox Code Playgroud)

然后在你的例子中使用它(顺序运行.then()):

 // On click button event...
 $("#printpng").click(function(){
    // Run operations sequentially
    loadPropsViaAjax().then(saveDocPropsViaAjax).then(waitForImageToload)
        .done(function(){
            window.location.href = "<?php echo $base_url ?>/sign/print"
     });
 });
Run Code Online (Sandbox Code Playgroud)

或者,如果它们可以并行运行,请使用$.when:

 // On click button event...
 $("#printpng").click(function(){
    // Run operations in parallel
    $.when(loadPropsViaAjax, saveDocPropsViaAjax, waitForImageToload)
        .done(function(){
            window.location.href = "<?php echo $base_url ?>/sign/print"
     });
 });
Run Code Online (Sandbox Code Playgroud)

  • 我的意思是Ajax停止事件中的超时(所以两者都有),但是"正确"的方法是让你可以捕获每个操作的完成事件*上的事件,点击触发*并将它们链接在一起(或组合承诺)并行运行它们并等待所有3).基本上还没有足够的信息来给出明确的答案. (2认同)

Soo*_*ead 6

只是为了正确起见,这可以通过jQuery Deferreds以干净的异步方式完成.这些对象代表将来完成的任务,事件处理程序可以附加到它的完成.您可以手动延迟调用完成.

对于具有回调的大多数异步任务,这些对象是jQuery在幕后使用的对象,您实际上可以等待它们完成.

您需要稍微更改一下代码.

在click eventhandler中#printpng,您需要为要完成的每个任务创建延迟对象.

假设你手动触发的所有3个点击事件都需要等待,所以我们创建3个延迟.

$('#printpng').click(function () {
    var def1 = $.Deferred();
    var def2 = $.Deferred();
    var def3 = $.Deferred();

    .......... other code not yet included
});
Run Code Online (Sandbox Code Playgroud)

现在我们有3个代表任务的对象.如果你打电话.resolve()给他们,这意味着任务完成.我们希望在#tool_export点击事件处理程序完成后完成这些任务.

假设这#tool_export有一个click事件处理程序,我们以某种方式能够将延迟对象传递给它.

$('#tool_export').click(function (e, deferred) {
    $.ajax({
        url: 'your_url',
        success: function(result){

            // your code does stuff with the result

            if (deferred !== undefined) {
                deferred.resolve();
            }
        },
        error: function(result){
            if (deferred !== undefined) {
                deferred.reject();
            }
        },
    });
});
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它会进行AJAX调用,deferred.resolve()如果调用成功并且出现问题deferred.reject()则会调用.非常简单.

现在的问题是:如何将此延迟参数传递给click事件处理程序?

你写:

$('#tool_docprops').click();
Run Code Online (Sandbox Code Playgroud)

这是一个简写:

$('#tool_docprops').trigger('click');
Run Code Online (Sandbox Code Playgroud)

要将def1对象作为参数传递,您只需编写:

$('#tool_docprops').trigger('click', def1);
Run Code Online (Sandbox Code Playgroud)

所以你的事件处理程序被修改为:

$('#printpng').click(function () {
    var def1 = $.Deferred();
    var def2 = $.Deferred();
    var def3 = $.Deferred();

    $('#tool_docprops').trigger('click', def1);
    $('#tool_docprops_save').trigger('click', def2);
    $('#tool_export').trigger('click', def3);

    ..... something is still missing from here
});
Run Code Online (Sandbox Code Playgroud)

您可以根据需要传递任意数量的参数.

最后要做的是总结这个延迟.有一个非常酷的辅助方法.when(),它等待解决任意数量的延迟.由于它也会创建延迟,因此您可以调用deferred.done()它来获取回调.所以要等待你之前创建的所有3个延迟,你可以写:

$.when(def1, def2, def3).done(function() { 
    window.location.href = "<?php echo $base_url ?>/sign/print";
});
Run Code Online (Sandbox Code Playgroud)

所以你的最终点击事件处理程序#printpng将是:

$('#printpng').click(function () {
    var def1 = $.Deferred();
    var def2 = $.Deferred();
    var def3 = $.Deferred();

    $('#tool_docprops').trigger('click', def1);
    $('#tool_docprops_save').trigger('click', def2);
    $('#tool_export').trigger('click', def3);

    $.when(def1, def2, def3).done(function() { 
        window.location.href = "<?php echo $base_url ?>/sign/print";
    });
});
Run Code Online (Sandbox Code Playgroud)

我做了一个非常简单的例子来说明这一点.没有ajax调用只有超时,但你可以得到这个想法.

如果单击start,则需要等待4秒才能完成:

http://jsfiddle.net/3ZDEe/2/