Можно ли заставить окно браузера обновляться, пока оно находится в цикле Javascript? - PullRequest
5 голосов
/ 03 февраля 2010

У меня есть вызов Ajax, который в настоящее время должен быть синхронным.Однако во время выполнения этого вызова Ajax интерфейс браузера останавливается до тех пор, пока вызов не вернется.В случаях таймаута это может заморозить браузер на значительный период времени .

. Есть ли способ заставить браузер (любой браузер) обновить пользовательский интерфейс, но не выполнитькакой-нибудь Javascript?В идеале это была бы какая-то команда типа window.update(), которая позволяла бы обновлять поток пользовательского интерфейса.

Если бы это было возможно, я мог бы заменить синхронный вызов AJAX чем-то вроде:

obj = do_async_ajax_call();
while (!obj.hasReturned()) {
  window.update();
}
// synchronous call can resume

Причина, по которой я не могу использовать setTimeout или возобновить функцию в обратном вызове, заключается в том, что поток выполнения не может быть прерван (слишком много переменных состояния, которые все зависят друг от друга, и long_function() поток в противном случае пришлось бы возобновить каким-либо образом):

function long_function() {
   // lots of code, reads/writes variable 'a', 'b', ...
   if (sync_call_is_true()) {
     // lots of code, reads/writes variable 'a', 'b', ...
   } else {
     // lots of code, reads/writes variable 'a', 'b', ...
   }
   // lots of code, reads/writes variable 'a', 'b', ...
   return calculated_value;
}

Ответы [ 4 ]

3 голосов
/ 03 февраля 2010

Вам необходимо заменить ваш синхронный запрос на асинхронный запрос и использовать обратный вызов. Упрощенный пример:

obj = do_async_ajax_call(function (data, success)
{
    if (success) 
    {  
        // continue...  
    } 
}); 

function do_async_ajax_call(callback)
{
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://mysite.com", true);
    xhr.onreadystatechange = function ()
    {
        if (xhr.readyState == 4 && xhr.status == 200)
            callback(xhr.responseXML, true);
        else if (xhr.readyState == 4)
            callback(null, false);
    }
    xhr.send();
}

Таким образом, вы передаете анонимную функцию в качестве параметра запрашивающей функции ajax. Когда ajax завершен, переданная функция вызывается с переданным ему responseXML. В то же время браузер может свободно выполнять обычные функции до завершения вызова. Отсюда и весь ваш код продолжается.

0 голосов
/ 03 февраля 2010

JavaScript является однопоточным. Таким образом, по определению вы не можете обновить пользовательский интерфейс, пока находитесь в цикле приливов. Однако, начиная с Firefox 3.5, добавлена ​​поддержка многопоточных скриптов JavaScripts, называемых веб-работниками. Веб-работники не могут влиять на пользовательский интерфейс страницы, но они также не будут блокировать обновления пользовательского интерфейса. Мы работники также поддерживаются Chrome и Safari.
Проблема в том, что даже если вы перенесете свой вызов AJAX в фоновый поток и дождитесь завершения его выполнения, пользователи смогут нажимать кнопки и изменять значения в вашем пользовательском интерфейсе (и, насколько я понимаю, это то, что вы пытаетесь избегать). Единственное, что я могу предложить, чтобы пользователи не могли вносить какие-либо изменения, - это счетчик, который блокирует весь пользовательский интерфейс и не допускает никакого взаимодействия со страницей, пока веб-вызов не вернется.

0 голосов
/ 03 февраля 2010

асинхронная выборка ajax, затем установка тайм-аута и выполнение обработки по частям (инициируется обратным вызовом)

0 голосов
/ 03 февраля 2010

Возьмите остаток вызова и поместите его в обратный вызов, который вызывается, когда возвращается результат. Я серьезно сомневаюсь, что это было бы совершенно невозможно для вас. Любая логика, которая вам нужна для вызова, может быть продублирована в обратном вызове

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