在插件中使用jquery延迟promise

时间:2015-03-05 03:51:36

标签: jquery ajax promise jquery-deferred

我编写了一个插件,它应该从API获取错误消息并将其显示在元素的HTML中。我想将它作为一个承诺来实现,以便可以通过donealways回调将其他事件链接到它。该插件的简化版本如下所示:

(function( $ ) {
     $.fn.flashAlerts = function() {
         var deferred = $.Deferred();

         var field = $(this);

         $.getJSON( "alerts", {})
         .done(function( data ) {
             // Display alerts
             field.html(data['message']);

             deferred.resolve();
         });
         return deferred.promise();
     };
 }( jQuery ));     

使用场景可能如下所示:

$("#myForm").submit(function(e) {
    e.preventDefault();

    var form = $(this);

    // Disable submit button
    form.disableSubmitButton();

    var serializedData = form.serialize();
    var url = form.attr('action');

    $.ajax({  
     type: "POST",  
     url: url,  
     data: serializedData       
    }).fail(function(jqXHR) {

       // Display errors on failure
       $('#alerts').flashAlerts().done(function() {
           // Re-enable submit button
           form.enableSubmitButton();
       });
    });
});

这个想法是强制执行以下一系列行动:

  1. 发布表单。在请求之前,请禁用“提交”按钮。请求完成后,
  2. alerts api获取错误。 请求完成后,显示错误消息。显示错误消息后,
  3. 重新启用提交按钮。
  4. 此代码似乎正常工作,但我不知道延迟是否按正确顺序工作(或者如果我对请求的时间安排感到满意)。

    那么,我这样做是否正确?我如何测试延期订单是否符合要求?

1 个答案:

答案 0 :(得分:1)

  

此代码似乎正常工作,但我不知道延迟是否按正确顺序工作

是的,他们按预期工作。

  

那么,我这样做是否正确?

不,您在flashAlerts方法中使用了deferred antipattern。此外,您忽略了从ajax请求到/alerts的错误,因此如果两个请求都失败,则不会重新启用该按钮。不确定这是否是您的意图,但我会使用.always代替.done进行最后一次回调。

以下是我写的内容:

 $.fn.flashAlerts = function() {
     var field = $(this);
     return $.getJSON( "alerts", {})
     .then(function(data) {
         // Display alerts
         field.html(data['message']);
         return data;
     });
 };
  

我如何测试延期订单是否符合要求?

没有多少要测试。通过您的代码布局方式,在form.enableSubmitButton();之前调用$('#alerts').flashAlerts()或在$.getJSON( "alerts", {})之前调用$.ajax({ … })是完全不可能的。当然,你必须相信那些在完成之前不能解决它们的功能的函数(正如你的代码所要求的那样),但是执行的顺序是不可克服的。