Правильно ли установить интервал, чтобы убедиться, что вызов Ajax завершен?

У меня есть два текстовых поля ввода и одна кнопка «Сохранить».

<input type="text" id="myInput" />
<input type="text" id="searchResult"/>
<button id="myButton>save</button>

В текстовом поле myInput есть событие onchange, которое затем отправляет запрос Ajax для получения некоторых данных и отображения результата в текстовом поле searchResult.

Кнопка сохранения имеет событие щелчка, которое проверяет ввод searchResult текстового поля на наличие пустой строки и т.п. Если все в порядке, продолжайте сохранение.

$("myInput").change(function() {
    var userInput = $("myInput").val(); //get value from the text field
    var responseText = callAjaxToGetData(userInput):  //XHR request to get some data

    $("searchResult").val( responseText ); //show the XHR result here

});


$("myButton").click(function() {
    var searchResultField = $("searchResult").val(); //get value from the searchResult field
    var isOK = validate(searchResultField);  //check empty string and such

    if(isOK) { saveDataViaAjax(userInput); }
});

Проблема

Когда пользователь вводит какой-либо текст в текстовое поле, а затем нажимает кнопку "save",

  1. onchange event срабатывает, callAjaxToGetData() вызывается. (XHR)

  2. до завершения callAjaxToGetData() и заполнения текстового поля searchResult срабатывает myButton onclick event.

  3. В обработчике события onclick проверка завершается ошибкой, так как поле searchResult все еще пусто.

  4. callAjaxToGetData() наконец заканчивает и заполняет текстовое поле searchResult.

В идеале callAjaxToGetData() сначала завершается, а затем переходит к процессу внутри события onclick, чтобы проверка не завершилась ошибкой.

Думаю, это очень распространенный случай, с которым люди могут столкнуться, поэтому мне интересно, как вы, ребята, подходите к этой проблеме?

Я думаю поместить интервал в событие onclick, как показано ниже (для этого требуется, чтобы responseText был глобальной переменной)

$("myButton").click(function() {

   var interval = setInterval(function() { //call every 500ms

       //if responseText is not null that means i know the ajax inside of onchange event is completed for sure.
       if( responseText != null ) {

           clearInterval(interval);

           var searchResultField = $("searchResult").val(); //get value from the searchResult field
           var isOK = validate(searchResultField);  //check empty string and such

           if(isOK) { saveDataViaAjax(userInput); }
       }
   }, 500);  
});

person Meow    schedule 15.06.2012    source источник
comment
После нажатия кнопки «Сохранить» вы проверяете, идет ли запрос, и ждете его завершения, а затем вызываете функцию подтверждения-сохранения. Другая проблема может заключаться в том, что вы слишком быстро меняете ввод, и запросы переходят в состояние гонки, поэтому вам нужно остановить первый запрос или проигнорировать его.   -  person jasssonpet    schedule 15.06.2012
comment
Здесь $.active может быть опцией..   -  person Meow    schedule 15.06.2012


Ответы (2)


Код ниже может быть неточным, но я бы отключил кнопку перед ajax и включил бы после возврата обратного вызова.

$("myInput").change(function() {
     $("myButton").attr("disabled", "disabled");
     var userInput = $("myInput").val(); //get value from the text field
     var responseText = callAjaxToGetData(userInput, function(data) {

        $("searchResult").val( data); //show the XHR result here
        $("myButton").removeAttr("disabled"); 
     }):
 });
person DanielEli    schedule 15.06.2012
comment
Вы имеете в виду, что событие щелчка для myButton будет запущено сразу после удаления отключенного атрибута из myButton??? Если да, то я не знал, что время триггера события можно контролировать таким образом. - person Meow; 15.06.2012
comment
Я попробовал приведенный выше код, и, поскольку кнопка отключена, событие щелчка не будет запускаться после события изменения. - person Meow; 15.06.2012
comment
эй, приведенный выше код отключает кнопку до тех пор, пока данные не будут получены. Затем кнопка снова активируется. (поскольку нажатие кнопки на самом деле не является допустимым вариантом, пока вызов не вернется.) Я надеюсь, что это поможет. - person DanielEli; 18.06.2012
comment
Я знаю ваше намерение, но я проверил ваш код, и событие клика не сработало. Событие мыши не будет срабатывать для отключенного элемента. - person Meow; 19.06.2012

Я думаю, что во избежание того, чтобы процесс onClick event шел быстрее, чем процесс ajax в onChange event, установка таймера решила проблему.

Сначала я создал вспомогательную функцию, которая проверяет активное соединение ajax и вызывает функцию, которая в противном случае вызывалась бы в событии onClick.

помощник

function check_pending_process(callback) {
    var interval = setInterval(function() {
        if($.active > 0) {
            //do nothing here
        }
        else {
            //no ajax is running, call the function after 500 ms
            clearInterval(interval);
            setTimeout(function() { window[callback].call() }, 500);
        }    
    }, 100);
}

звонящий

function processButtonClick() {
    var searchResultField = $("searchResult").val(); //get value from the searchResult field
    var isOK = validate(searchResultField);  //check empty string and such

    if(isOK) { saveDataViaAjax(userInput); }

}

$("#myButton").click(function() {

    check_pending_process("processButtonClick");

});

Оценка 500 мс основана на том, сколько времени занимает процесс post-ajax в событии onchange. В моем случае процесс post-ajax внутри события onchange просто помещает текст ответа в текстовое поле, поэтому 500 мс достаточно.

person Meow    schedule 15.06.2012