JQuery AJAX проблемы, периодически получая дубликаты запросов - PullRequest
6 голосов
/ 01 июля 2010

В этот момент я заканчиваю переписывание нашей системы JavaScript, мы переходим от Prototype к jQuery.У нас есть загрузка AJAX-запросов, которые запускаются при возникновении определенных событий элемента, в приведенном ниже примере это новое событие в календаре, но оно происходит и в других местах.

Проблема, которую я получаю, заключается в том, когдасобытие запускается иногда два AJAX-запроса.Первый возвращает правильное значение, но (как вы можете видеть) он все еще говорит об обработке, он никогда не возвращает сообщение об успешном выполнении, которое требует мой JavaScript.Второй запрос возвращает правильный результат И завершается правильно.

Проблема, с которой я столкнулся, заключается в том, что наш блокировщик экрана jQuery настроен на предотвращение пользовательского ввода во время тяжелых запросов AJAX, очевидно, потому что запрос AJAX все еще жив, экран никогда не разблокируется.Если я обновлю этот экран, все будет работать так, как нужно.

Может ли кто-нибудь пролить свет на то, почему это происходит.

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

РЕДАКТИРОВАТЬ

«Запросы, которые запускаются, когда происходят события определенного элемента» - это ключевая фраза, я думаю.Пожалуйста, предоставьте некоторую информацию о том, как вы устанавливаете свои события.Может быть, он срабатывает дважды, потому что у вас установлено несколько обработчиков?- Игорь Зиновьев

Хорошо, дело в том, что когда я нажимаю «Обновить», проблема обычно разрешается сама собой, поэтому не уверен, как это может быть проблемой с обработчиком, вот обработчик событий, который мы обычно используем для измененияокна выбора.

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

Проблема, с которой я столкнулся, заключается в том, что я понятия не имею, как воспроизвести проблему, поэтому я не знаю, запускается ли событие несколько раз или запрос AJAX выполняется дважды.

РЕДАКТИРОВАТЬ 2

Если вы перезагружаете связанные элементы, то события изменения могут запускаться рекурсивно ... Нам действительно нужно увидеть больше кода(что вы делаете в случае успеха вызова ajax и т. д.) - redsquare

Спасибо, redsquare, при успешном запросе AJAX я обычно применяю ответ (обычно HTML <option> s) к цели.Я никогда не инициирую изменение элемента, который запустил 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
    });

}

Другой способ остановить несколько запросов AJAX - это хекнуть jQuery.active до вызова.jQuery ведет внутренний подсчет «живых» ajax-запросов, используя это свойство.- redsquare

Я посмотрю на это.

РЕДАКТИРОВАТЬ 3

Так что это результат $ ('element') .data (), но я не могу понять, что он пытается сказать, значит ли это, что есть две привязки к нему.Если да, то как мне узнать, что это за привязки и почему они не срабатывают при запуске события.

альтернативный текст 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, «Строка 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

Ответы [ 4 ]

1 голос
/ 15 июля 2010

Правильно, поэтому я пришел к выводу, я почти уверен, что моя проблема связана с Firebug, так как я протестировал его на FF без включенного Firebug, и он работает, как и должен.

Это не первый раз, когда что-то, связанное с JavaScript, приводит меня к веселому танцу, когда симптомы, вызванные проблемой, не дают никакого разумного намека на решение, но у нас это есть.

Огромное спасибо @redsquare, который здесь очень помог, но через твиттер и канал jQuery IRC, большое спасибо, чувак!

1 голос
/ 01 июля 2010

Вы пытались использовать вместо этого .click ()?У меня были проблемы с нерегулярной деятельностью с использованием .change () в JavaScript.Дайте этому попытку.

0 голосов
/ 29 октября 2017

Я пытался это :

$(selector).unbind().on(eventname,function(){
    $.ajax({
        //ajax code here
    });
});

Работало.

0 голосов
/ 01 июля 2010

Попробуйте добавить return false к вашей функции onchange.Это остановит jQuery от всплытия события.

Вы должны убедиться, что $("#my_select","#context").change(function(){ вызывается только один раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...