jQuery AJAX问题,间歇性地获取重复请求

Ben*_*ard 6 javascript ajax jquery

就在那时,我即将重写我们的JavaScript系统,我们正在从Prototype转向jQuery.我们有一大堆AJAX请求在某个元素事件发生时触发,下面示例中的一个是日历上的新事件,但它也发生在其他地方.

我遇到的问题是当事件被触发时有时会发出两个AJAX请求.第一个返回正确的值,但(如您所见)它仍然表示处理,它永远不会返回我的JavaScript所需的成功消息.第二个请求返回正确的结果并正确终止.

我遇到的问题是我们的jQuery屏幕拦截器设置为在重大的AJAX请求期间阻止用户输入,显然是因为有一个AJAX请求仍然存在,屏幕永远不会解锁.如果我要刷新此屏幕,则所有内容都将按预期工作.

任何人都可以阐明为什么会发生这种行为.

alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request.png

编辑

"当某个元素事件发生时会触发" - 我认为这是关键词.请提供有关如何设置活动的一些信息.也许它会因为你有多个处理程序而触发两次? - Igor Zinov'yev

好吧,问题是当我点击刷新时,问题通常会自行解决,所以不确定这可能是一个处理程序问题,这里是我们通常用于更改选择框的事件处理程序.

$("#my_select","#context").change(function(){
            // uz_ajax is a wrapper function, keeps most of the same functionality as $.ajax()
    uz_ajax({
        target:"#my_target",
        data:{
            module:'my_module',
            controller:'my_controller',
            action:'my_action',
            id:$(this).val(),
            ajax:''
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我不知道如何复制问题,因此我不知道该事件是否被多次触发或者AJAX是否请求两次.

编辑2

如果你正在重新加载绑定的元素,那么可以递归地触发更改事件......我们真的需要看到更多代码(你在ajax调用成功时做了什么等) - redsquare

感谢redsquare,在成功的AJAX请求后,我通常将响应(通常是<option>s的HTML )应用于目标.我永远不会从触发AJAX的元素触发更改,但我有时会触发对目标元素的更改,以允许级联AJAX请求.如果这是问题,肯定会一直发生这种情况?我的包装函数uz_ajax如下:

var ajax_count = 0;
var ajax_response = null;

function uz_ajax(options) {

    // set default options
    var defaults = {
        async: true,
        type: "GET",
        data: {},
        url: "/",
        cache: false,
        force_change: true,
        highlight: true,
        action: "normal",
        dataType: "html",
        selected: {
            value: null,
            disabled: false
        }
    };

    // merge the passed options with the defaults
    var options = $.extend(defaults, options);

    // start the jQuery ajax method
    $.ajax({
        async: options.async,
        type: options.type,
        url: options.url,
        data: options.data,
        beforeSend: function() {
            // we only want to block the screen on the first pass
            if(++ajax_count==1) {
                $.blockUI({message:'Loading data, please wait'});
            } 
        },
        success: function(responseText) {           
            if(options.target!==undefined) {
                // if target isn't an array, make it one
                if(!$.isArray(options.target)) {
                    options.target = new Array(options.target);
                }

                var targets = options.target;

                for ( var i in targets ) {
                    console_info("uz_ajax() --> Applying contents to "+targets[i]);

                    switch(options.action) {
                        case "normal":
                            if($(targets[i]).is("input")) {
                                $(targets[i]).val(trim(responseText));
                            } else {
                                $(targets[i]).html(trim(responseText));
                            }
                            break;
                        case "selected":
                            // preserve the current target value (e.g. list of options), but 
                            // set the selected value to the ajax response
                            console_warn("Changing selected value of "+targets[i]+" to '"+responseText+"'");
                            // trim the response so we don't get any smarty induced errors such as '    7'
                            $(targets[i]).val(trim(responseText));
                            break;
                    }

                    // set selected value
                    if(options.selected.value!=null) {
                        $(targets[i]).val(options.selected.value);
                    }

                    // highlight the target
                    // we don't want to highlight the target if it's a hidden input, as this will force a .show(
                    if($(targets[i]).attr('type')!='hidden' && options.highlight===true) {
                        $(targets[i]).effect("highlight",{},2000);
                    }

                    // force the target to change
                    if(options.force_change===true) {
                        $(targets[i]).trigger("change");    
                    }

                    /* rebind certain elements that do not use conventional events */
                    /* We probably need to get all of these rebinds in a single function */
                    createDatePickers(targets[i]);
                }
            } else {
                ajax_response = responseText;
                console_warn("uz_ajax -> no targets specified");
                // Well... we have no element to target, we need to return the value instead
                // of course if we return here we're going
                // we probably also need to check the ajax count as this will be the last executed part before we return
            }
        },
        complete: function () {
            /* if all ajax requests have completed, unblock screen */
            if(--ajax_count===0) {
                $.unblockUI();
                /* could use this callBack to return a value *dun dun duuuuun* */
                if (options.ajaxComplete) {
                    options.ajaxComplete(ajax_response);
                }
            }
        },
        cache: options.cache,
        dataType: options.dataType
    });

}
Run Code Online (Sandbox Code Playgroud)

停止多个ajax请求的另一种方法是在调用之前检查jQuery.active.jQuery使用此属性保留"实时"ajax请求的内部计数.- 红方格

我会调查一下.

编辑3

所以这是$('element').data()的结果,但是我无法理解它试图说的是什么,这是否意味着它有两个绑定.如果是这样,我如何找出这些绑定是什么以及为什么它们都不会在事件被触发时触发.

alt text http://archive.ilmv.co.uk/images/firebug-jquery-data-events.png

编辑4

这是问题的另一个屏幕截图,这次是在系统的另一个地方.绿色箭头是触发三个ajax请求的元素,而不是在firebug中如何有六个,并且它们配对并将时间戳分配到毫秒级?

前三位是尚未完成的,前三位是返回正确的结果.

替代文字http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v2.png

编辑5

下图显示了更改选择框时会发生什么,它会触发三个不同的ajax请求.

我设法做了一些调试,我可以告诉你以下内容:

  1. 无论有多少ajax请求初始元素调用,都会出现问题
  2. 无论使用什么插件,都会出现问题
  3. 这个事件肯定只被解雇过一次
  4. 我的uz_ajax包装器函数每个目标只被触发一次(参见firebug控制台,"Line 29:uz_ajax()").
  5. 我已经添加console.info了每个jquery $.ajax()回调以查看触发的内容以及何时触发,请注意唯一的触发回调是什么beforeSend().

替代文字http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v3.png

编辑6

就在那之后,在@redsquare通过Twitter建议console.trace()用来找出"第二个事件从哪里开火"之后,就像我一直保持着我确定没有两个事件被触发所以我把踪迹放在$.ajax()方法中,这是发生了什么:

替代文字http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v4.png

正如您所看到的,即使$.ajax()方法仅触发一次,我也会得到重复的ajax请求问题,时间戳也是相同的.我遇到过jQuery的错误吗?

编辑7

它也发生在StackOverflow上!

alt text http://archive.ilmv.co.uk/images/jquery-duplicate-ajax-request-v5.png

Ben*_*ard 1

是的,所以我得出了一个结论,我很确定我的问题是 Firebug 的问题,因为我在没有打开 Firebug 的情况下在 FF 上测试了该应用程序,并且它可以正常工作。

这并不是第一次当问题引发的症状没有为解决方案提供任何合理的提示时,与 JavaScript 相关的事情让我高兴地跳舞,但我们已经有了。

非常感谢 @redsquare,他在这里提供了大量帮助,但是通过 twitter 和 jQuery IRC 频道,非常感谢老兄!