2010-02-03 57 views
5

我有一个目前需要同步的Ajax调用。但是,在执行此Ajax调用时,浏览器界面会冻结,直到调用返回。在超时的情况下,这可以冻结浏览器significant period of time是否有可能在浏览器窗口在Javascript循环中更新?

有什么办法让浏览器(任何浏览器)刷新用户界面,但不执行任何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; 
} 
+2

为什么呼叫需要同步? – 2010-02-03 00:08:03

+1

你可以发布整个通话代码吗?这可能可以简化,并使用XHR函数来支持你需要的东西(除非jQuery是一个选项,然后更清洁)。如果这两个选项都不是,我要求你将该函数重命名为'do_sync_jax_call();' – 2010-02-03 00:08:28

回答

3

你需要用替换您的同步请求异步请求并使用回调。过于简单的例子是:

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

这通常就足够了,但我不能拆分操作流程(在问题中更新)。我正在尝试另一种方法... – jevon 2010-02-03 00:51:46

+0

它*总是*可能分裂它;这是CPS转换(查找“延续传递样式”;延续参数是您的回调)。您的本地状态变量只需在回调函数中关闭即可。循环成为递归调用。一旦掌握了它并不难,也不难理解。 – 2010-02-03 03:49:56

+0

我同意它总是可能的,但在这种情况下,它不是最好的解决方案(有太多的状态变量!):)最后,我用前面的回调(或常规服务器轮询)的结果来更新客户端在需要的时候使用同步调用的缓存值,所以它根本不需要调用Ajax。 – jevon 2010-02-03 04:02:33

0

接电话的其余部分,并把它在回调中当结果回来时被调用。我严重怀疑这是完全不可能的。你需要把在呼叫的任何逻辑可以在回调中重复再

0

AJAX的异步读取setTimeout和做以块的处理工作(由回调触发)

0

JavaScript是单线程的。因此,根据定义,当您处于潮汐循环中时,您无法更新UI。但是,从Firefox 3.5开始,它增加了对称为Web工作者的多线程JavaScript的支持。 Web工作人员不能影响页面的UI,但他们也不会阻止UI的更新。我们的工作人员也受到Chrome和Safari的支持。
问题是,即使您将AJAX调用移动到后台线程并等待执行完成,用户也将能够按下按钮并更改UI上的值(并且据我所知,这就是您试图避免)。我可以建议阻止用户进行任何更改的唯一方法是一个微调器,它将阻止整个用户界面,并且在Web通话返回之前不会允许与该页面进行任何交互。

+0

我不介意用户是否与页面交互(并且交互是排队的);但目前,在Firefox中执行同步Ajax调用时,整个浏览器都会冻结。这是我想要防止的。 – jevon 2010-02-03 03:54:19

相关问题