简体   繁体   English

如何让某人在jQuery插件上链接回调方法?

[英]How do I let someone chain callback methods on my jQuery plugin?

I am wanting to to provide some extra functionality to jQuery.post(). 我想为jQuery.post()提供一些额外的功能。 I want to be able to check the response from the server and call different callbacks. 我希望能够检查服务器的响应并调用不同的回调。

For example: 例如:

$("#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(); });

So I want to be able to send back a consistent JSON object back to the page and based on that JSON object either call success or validationError providing additional info to validationError. 因此,我希望能够将一致的JSON对象发送回该页面,并基于该JSON对象调用成功或validationError,以向validationError提供其他信息。

UPDATE It has been a steep learning curve and I am almost 100% sure that I have done something wrong. 更新这是一个艰难的学习过程,我几乎100%确信自己做错了什么。 Below is my attempt at the functionality that I wanted. 以下是我对所需功能的尝试。

(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);

So how bad is what I have done? 那我做得有多糟? I am not familiar with javascript and jQuery and I am sure that I am breaking some rules that is bound to bite me. 我对javascript和jQuery不熟悉,并且我确定自己违反了一些必定会咬我的规则。

It's not very practical to do what you're proposing because it effectively changes the promise interface. 按照您的建议进行操作不是很实际,因为它会有效地更改promise接口。

Note that much of what you want does already exist if you just return the result of $.post to the caller: 请注意,如果您只是将$.post的结果返回给调用者,则您想要的大部分已经存在:

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

So, you have to show the spinner first, but that's barely any hardship, and there's no way to catch the validation error, so that would need to be part of your .done function. 因此,您必须先显示微调器,但这几乎没有什么困难,并且没有办法捕获验证错误,因此这需要成为您.done函数的一部分。

If i understand correct what you want to achieve, you should use $.ajax() . 如果我正确理解您要实现的目标,则应使用$ .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     
     }
  }

You are looking for $.Deferred (or $.Callbacks if you want something really custom), or more generally the promise pattern . 您正在寻找$ .Deferred (或$ .Callbacks,如果您想要真正自定义的东西),或更普遍的是promise模式 A simple implementation might look something like this: 一个简单的实现可能看起来像这样:

(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);

This does not differentiate between error / validationError , but gets rid of most of the biolerplate code. 这不能区分error / validationError ,但是摆脱了大部分biolerplate代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM