I have an Ajax call that currently needs to be synchronous. However, while this Ajax call is executing, the browser interface freezes, until the call returns. In cases of timeout, this can freeze the browser for a significant period of time.
Is there any way to get the browser (any browser) to refresh the user interface, but not execute any Javascript? Ideally it would be some command like window.update()
, which would let the user interface thread refresh.
If this would be possible, then I could replace the synchronous AJAX call with something like:
obj = do_async_ajax_call();
while (!obj.hasReturned()) {
window.update();
}
// synchronous call can resume
The reason that I can't use setTimeout
, or resume a function in t开发者_JAVA百科he callback, is that the execution flow cannot be interrupted: (there are far too many state variables that all depend on each other, and the long_function()
flow would otherwise have to be resumed somehow):
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;
}
You need to replace your synchronous request with an asynchronous request and use a callback. An oversimplified example would be:
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();
}
This way you're passing an anonymous function as a parameter to the ajax requesting function. When the ajax is complete, the function that was passed is called with the responseXML passed to it. In the meantime, the browser has been free to do it's usual thing until the call completes. From here, the rest of your code continues.
Take the rest of the call and put it in the callback that is called when the result comes back. I seriously doubt that this would be completely impossible for you to do. Any logic you need to put in the call can be duplicated in the callback
asynchronous ajax fetch then settimeout and do the processing work in chunks (triggered by the callback)
JavaScript is single-thread. So by definition, you cannot update UI while you are in a tide loop. However, starting from Firefox 3.5 there's added support for multi-threaded JavaScripts called web workers. Web workers can't affect UI of the page, but they will not block the updates of the UI either. We workers are also supported by Chrome and Safari.
Problem is, that even if you move your AJAX call into background thread and wait of execution to complete on it, users will be able to press buttons and change values on your UI (and as far as I understand, that's what you are trying to avoid). The only thing I can suggest to prevent users for causing any changes is a spinner that will block the entire UI and will not allow any interaction with the page until the web-call returns.
精彩评论