2012-11-16 25 views
0

我想为jQuery.post()提供一些额外的功能。我希望能够检查服务器的响应并调用不同的回调函数。如何让我的jQuery插件的连锁回调方法?

例如:

$("#frmFoo").postForm("ajax") 
    .start(function() { showSpinner(); }) 
    .success(function() { alert ("Foo saved"); }) 
    .error(function() { alert ("Foo could not be saved at this time"); }) 
    .validationError(function() { alert("Please fix foo and try again"); }) 
    .complete(function() { hideSpinner(); }); 

所以我希望能够发回一个一致的JSON对象返回到页面并根据该JSON对象或者调用成功或validationError到validationError提供额外的信息。

UPDATE 这是一个陡峭的学习曲线,我几乎100%肯定我做错了什么。以下是我想要的功能的尝试。

(function ($) { 
    $.fn.postForm = function (url) { 
     var options = options || {}; 
     var formData = this.serialize(); 
     var validationCb = jQuery.Callbacks("once memory"); 
     var successCb = jQuery.Callbacks("once memory"); 
     var errorCb = jQuery.Callbacks("once memory"); 
     var completeCb = jQuery.Callbacks("once memory"); 
     var s = jQuery.ajaxSetup({ }, options); 
     var callbackContext = s.context || s; 
     foo = { 
      success: function() { 
       successCb.add(arguments[0]); 
       return this; 
      }, 
      complete: function() { 
       completeCb.add(arguments[0]); 
       return this; 
      }, 
      validationError : function() { 
       validationCb.add(arguments[0]); 
       return this; 
      }, 
      error: function() { 
       errorCb.add(arguments[0]); 
       return this; 
      } 
     }; 
     $.post(url, formData) 
      .success(function(data, textStatus, jqXhr) { 
       if (!data.Success) { 
        validationCb.fireWith(callbackContext, [data.Message, data.KeyValuePairs]); 
       } else { 
        successCb.fireWith(callbackContext, [data, textStatus, jqXhr]); 
       } 
      }) 
      .complete(function (jqXhr, textStatus) { 
       completeCb.fireWith(callbackContext, [jqXhr, textStatus]); 
      }) 
      .error(function(jqXhr, textStatus, errorThrown) { 
       errorCb.fireWith(callbackContext, [jqXhr, textStatus, errorThrown]); 
      }); 
     return foo; 
    }; 
})(jQuery); 

因此,如何坏的我做了什么?我不熟悉JavaScript和jQuery,我相信我打破了一些必然会咬我的规则。

回答

1

这不是很实用的做你提出什么,因为它有效地改变了promise接口。

注意,很多你想要的东西不存在,如果你只是返回$.post结果给调用者:

showSpinner(); 
$.post({...}) 
    .done(...)   // aka .success (deprecated) 
    .fail(...)   // aka .error (deprecated) 
    .always(stopSpinner) // aka .complete (deprecated) 

所以,你必须首先显示的微调,但是这几乎没有任何困难,并无法捕捉验证错误,因此需要将其作为您的.done函数的一部分。

+0

你是否可以解释一下当你说我正在改变承诺界面时你的意思?我能否将我的插件包装在$ .post或ajax方法中?我不介意是否需要更改回调名称以避免冲突。 – uriDium

+0

我也非常希望能够以那简洁的方式链接回调。 – uriDium

+0

@uriDium这就是问题所在 - 要链接你或者需要增加或者复制类似于'$ .Deferred()'的东西 - 你需要传递一个对象来维护一个单独的回调列表,并且知道哪些对象必须被调用取决于你的内部'$ .post()'调用做了什么。 – Alnitak

0

如果我理解你想要达到的目标,你应该使用$.ajax()

$.ajax({ 
    url: your_url, 
    type: 'POST' 
    beforeSend: function(){ showSpinner(); }, 
    error: function() { alert ("Foo could not be saved at this time"); } 
    success: function (data) { 
    if (data.validation == true) { //example of validation, depends on how you send data from backend 
     alert ("Foo saved"); 
     hideSpinner(); 
    } else { 
     alert("Please fix " + data.foo + " and try again"); //again depends on how you send data  
    } 
    } 
+0

不,你完全错过了这一点。我想拦截JSON并检查是否进行验证并提供钩子来执行自定义事情。我不知道他们还有什么,我希望其他人能够做到。我想让它成为团队中其他人使用的插件。 – uriDium

0

您正在寻找$.Deferred(或$.Callbacks如果你想要的东西真的定制),或更一般的promise pattern。一个简单的实现可能是这个样子:

(function ($) { 
    $.fn.postForm = function (url, options) { 
     var options = options || {}, 
      s = jQuery.ajaxSetup({ }, options), 
      callbackContext = s.context || s; 

     var formData = this.serialize(); 
     var post = $.post(url, formData); 
     var deferred = post.pipe(function(data, textStatus, jqXhr) { 
      if (!data.Success) { 
       // HTTP OK, soft error 
       return $.Deferred().rejectWith(callbackContext, [data.Message, data.KeyValuePairs]); 
      } else { 
       // success 
       return $.Deferred().resolveWith(callbackContext, [data, textStatus, jqXhr]); 
      } 
     }, function(jqXhr, textStatus, errorThrown) { 
      // HTTP error 
      return $.Deferred().rejectWith(callbackContext, [errorThrown, {}]); 
     }); 

     deferred.success = deferred.done; 
     deferred.error = deferred.fail; 
     deferred.complete = deferred.always; 

     return deferred; 
    }; 
})(jQuery); 

这并不error/validationError区分,但摆脱了大部分biolerplate代码。

+0

我需要区分两者。 – uriDium

相关问题