2009-09-20 41 views
6

我正在写一个无处不在的插件长时间的函数回调为ajax查询阻止了GUI线程导致Firefox锁定。有没有一种正确的方式来在JavaScript的协作线程意义上“屈服”?

显而易见的解决方案似乎是使用某种延迟执行(即我们要定期添加执行此查询函数到事件队列的末尾,然后允许执行其他命令。

我能想到这样做的唯一方法是使用的setTimeout为零的超时...这是保证工作,或者是有这样做的更好的方法。

+0

你是怎么做AJAX的?如果您正在加载脚本标记,则可能会阻止(浏览器阻止,直到脚本返回)。 – 2009-09-21 04:16:06

+0

我正在使用jQuery.get – user47741 2009-09-21 13:46:16

回答

7

使用setTimeout与一个非常小的超时(0或几乎为零,如果你觉得偏执)是在浏览器上下文中执行此操作的唯一方法。工作得很好,非常可靠,但一定要足够频繁,但不要太经常 ,因为它需要一段时间才能回到你身边(当然,在计算机意义上的“一段时间”它几乎是瞬时的[用人的话来说,你可能正在做其他事情])。

+2

所有现代浏览器实现都将setTimeout限制在〜10ms(基本上在所有非Windows系统上为10ms,其中定时器分辨率要求<16ms定时器对功耗有显着影响)。所以你并不需要担心缩短超时时间。 – olliej 2009-09-20 23:32:34

+1

@olliej:那是过时的信息(如果它在'09中是正确的,但是那也不是我的经验)。浏览器的处理比这更复杂,这取决于'setTimeout'调用的起源。这是[几年前在HTML5规范中编纂](http://www.w3.org/TR/html5/webappapis.html#timer-initialization-steps),但正如我所说,供应商已经在玩(不同)之前的游戏。短版本:如果你的代码没有被定时器调用,你可以使用0,而现代浏览器会得到**非常**。 – 2015-10-21 11:57:21

3

请确保您使用异步请求作为同步请求阻止浏览器(这将解释GUI锁定)。

如果这不是你的问题,我想你想要这样的任务队列。

var queue = []; 

queue.push(someTaskFunction); 
queue.push(anotherTaskFunction); 
// ... 

var runQueue = (function() { 
    var len = queue.length, task = 0; 
    for (; task < len; task++) { 
     yield queue[task](); 
    } 
}()); 

呼叫runQueue.next()执行下一个任务。用try..catch语句包装它:

try { 
    runQueue.next(); 
} catch (e if (e instanceof StopIteration)) {} 
+0

该调用是异步的 – user47741 2009-09-20 22:14:41

+0

酷 - 我不知道发电机已被添加到JavaScript。我理解其他任务可以在函数返回时进行控制吗? – user47741 2009-09-20 22:18:04

+0

请注意,生成器对于JavaScript来说比较新,不一定得到广泛支持。 – 2009-09-20 22:25:34

相关问题