【问题标题】:How do I extend JQuery's ajax done() method?如何扩展 JQuery 的 ajax done() 方法?
【发布时间】:2015-09-24 01:46:54
【问题描述】:

我有一个这样的 jQuery ajax 函数:

jQuery.ajax({
            url : '/blabla',
            method : 'post',
            data: {
                bla : bla
            }
        }).done(function(data) {
            // do lots of stuff
        });

.. 并且我希望能够添加检查传递给完成回调函数的数据中没有 session_timed_out 值。假设我有许多与上面类似的功能,但它们都做不同的事情,但它们都需要先检查会话是否超时。是否有适当的方法来扩展 done() 以便它最初检查超时?我试图做这样的事情,但失败了:

var myAjax = function(options,callback){ 
    var defaults = {              
        done: function(data){  //hijack the success handler?
            if(check(data)){    
                callback(data); 
            }
        }
    };
    jQuery.extend(options,defaults);  
    return jQuery.ajax(options); 
}

当我使用这个扩展函数时,它像以前一样工作,这意味着检查永远不会被调用,因为它似乎被实际实现中的 done() 回调所取代,我想这是有道理的。所以我想知道是否有办法“装饰”或扩展 done() 函数,以便它首先检查会话超时。或者我是否需要手动将相同的会话检查添加到我所有的 ajax 完成中?

【问题讨论】:

标签: javascript jquery ajax


【解决方案1】:

这个 sn-p 覆盖了 jQuery ajax 方法,因此您可以在它成功返回时添加额外的检查。

(function($) {

    var yourCustomCheck = function(ajaxRes) {
        // Do whatever you need and return a boolean
    };

    var oldAjax = $.ajax;
    $.ajax = function(opts) {
        return $.Deferred(function() {
            var _def = this;

            oldAjax.call(this, opts).done(function(res) {
                console.log("this is done first");
                if(yourCustomCheck.call(this, res)) _def.resolve(res);
                else _def.reject("timeout");
            }).fail(function() {
                _def.reject();
            });
        })
    }

})(jQuery);

之后就可以正常使用$.ajax()了..

$.ajax({
    .....
}).done(function(res) {
    console.log("ok");
}).fail(function() {
    console.log("no ok");
});

这是一个带有工作示例的 jsfiddle:https://jsfiddle.net/jormaechea/kffyo7qL/1/

【讨论】:

  • 我会看看我能不能让它工作。目前,当我这样做时:console.log(ajaxRes);在 yourCustomCheck() 方法中 - 我没有得到 ajax 响应,我得到了我当前所在页面的 html。我看看能不能解决。
  • 刚刚修改了这个以修复您报告的内容。请再次检查并告诉我..
  • 对不起华金。当我控制台记录 ajaxRes var 时,我仍然得到我所在页面的 html。我感谢您的努力,并会为您投票。
  • Weird.. 刚刚在 jsfiddle 中再次测试它并且工作正常.. 我用测试用例链接更新了我的答案..
  • @JoelJoelBinks - 这被认为是promise anti-pattern,因为它创建了一个新的承诺,而不是在不需要时使用已经返回的承诺。这不是一个好习惯。此外,将$.ajax() 替换为与标准行为不同的替代品意味着您的代码将不兼容任何也使用jQuery ajax 的第三方库。这也不是一个好的做法。最好用新行为创建一个新函数。
【解决方案2】:

你可以链接一个超时检查器:

   jQuery.ajax({
        url : '/blabla',
        method : 'post',
        data: {
            bla : bla
        }
    }).then(timeoutCheck).then(function(data) {
        // do lots of stuff
    }, function(err) {
        // handle error
    });

    function timeoutCheck(data) {
        if (check(data)) {
           return data;
        } else {
           // return a rejected promise to turn fulfilled into reject
           return jQuery.Deferred.reject(new Error("timeout"));
        }
    }

或者,您可以将其放入您自己的 ajax 包装器中。

jQuery.ajaxT = function() {
     return jQuery.ajax.apply(jQuery, arguments).then(timeoutCheck);
}

jQuery.ajaxT(...).then(function(results) {
    // handle returned data here
    // the timeoutCheck has already been done
}, function(err) {
    // handle any errors here
});

然后,您使用jQuery.ajaxT() 发起的任何 ajax 调用都会自动将 timeoutCheck 添加到它的承诺逻辑中。如果 ajax 调用成功并且超时检查通过,那么 Promise 就实现了。如果 ajax 调用成功,超时检查失败,则 Promise 被拒绝。

【讨论】:

  • @user2864740 - 是的,它会,但它比 OP 所做的要干净得多,它为任何给定请求的正确错误处理提供了一个通道。对于您希望运行此检查的 ajax 调用,这是一个额外的 .then(timeoutCheck)。可以使用自定义包装函数包装 jQuery.ajax() 并在那里执行此操作,然后在需要此额外代码时调用自定义包装函数。
  • @user2864740 - 我添加了一个包含内置功能的函数包装器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 1970-01-01
  • 2014-08-14
  • 2011-08-03
  • 1970-01-01
  • 2010-11-18
  • 2012-08-29
相关资源
最近更新 更多