我有一个web应用程序,其中有一个不断倒计时的计时器。同时,客户端频繁地与服务器进行检查,以查看是否向计时器添加了更多时间。代码看起来像这样:
function tick() {
// This function is called once every second
time -= 1;
redisplay(time);
};
function update(newtime) {
// This function is called whenever the ajax request
// to the server yields a new time
time = newtime;
};
当然,这要比这复杂一点,但您可以看到固有的竞争条件。如果update和tick函数都试图同时修改time
,该怎么办?
坦率地说,我对javascript的了解还远远不够,无法理解如何处理这种并发问题:有没有一种简单的方法可以做到这一点,或者如果没有,有人能告诉我在哪里可以学到更多?
谢谢。
发布于 2010-01-17 03:36:49
您没有竞争条件,因为Javascript不会并发执行。
每次从异步操作(AJAX、setTimeout
等)触发回调时,必须先完成该回调的执行,然后才能调用另一个异步操作的另一个回调。因此,如果update()
正在运行,则没有其他Javascript在运行。一旦update()
完成,就可以触发来自异步操作的其他回调(例如,tick()
)。有趣的是,这也是为什么setTimeout
和它的同类不能保证在到达超时的精确时刻执行的原因:一些其他的javascript可能会阻塞回调的执行。
请查看http://ejohn.org/blog/how-javascript-timers-work/,了解有关这一切如何工作的一些好信息。
发布于 2010-01-17 03:35:48
Javascript是单线程的。没有竞争条件。在javascript中,time = newtime;
和time -= 1;
这两行代码不可能在执行过程中重叠。事实上,这两个功能可以保证不会重叠。它们中的一个将运行,然后另一个将运行。
发布于 2010-01-17 03:14:09
这个问题需要一些信号量。我在前一个完成后发送ajax做了很多这样的事情。你的情况有点相似;)
试试这样的东西。它应该忽略与ajax回调冲突所有减少时间的尝试。
window.TimeKeeper = new function(){
this.time=0; //initial value, whatever
this.isopen=true;
this.decrement = function(){
if(this.isopen){
this.time--;
redisplay(this.time);
}
}
this.set = function(val){
if(this.isopen){
this.isopen=false;
this.time=val;
this.isopen=true;
} else {
//another AJAX callback is modifying time.
//You can enqueue current value and put it later
}
}
}
function tick() {
TimeKeeper.decrement();
};
function update(newtime) {
TimeKeeper.set(newtime);
};
还有一件事- setTimeout的工作方式就像一个新的线程,我希望浏览器会同步内存访问,所以在减少之前检查一下这个值是否没有增长就足够了。但上述解决方案更加灵活和安全。
还有一个小技巧-避免太频繁地使用AJAX查询-这可能会导致额外的问题-比如请求返回的顺序与发送的顺序不同,以及firefox内存使用量在一分钟内因ajax太多而积累了很多;)
https://stackoverflow.com/questions/2078235
复制相似问题