1

我有一个网页(javascript),它有两种类型的事件:

  • 画布中的单击事件(仅显示警报)。
  • 每秒的周期性事件(由计时器触发)。

周期性事件忙了 200 - 300 毫秒(它正在启动同步 SOAP 调用)。

画布事件:

var c=document.getElementById("myCanvas");
 c.addEventListener('click', function(e) {alert('Click');},false);

定期:

var timer1= new Timer(1000,"Refresh()"); // A library call


function Refresh()
{   
    timer1.stop();

    // Synchronous SOAP call would come here

    // with the results we draw the canvas again

    timer1.start();
}

如果在进行 SOAP 调用时单击画布,则不会触发 click 事件,或者我假设是这样,因为未显示警报。

如果我在定期事件完成并再次调用它之前单击,则每次单击都会显示警报。

据我所知,如果在执行周期性事件时生成了单击事件,则应该延迟到另一个事件完成。

什么可能导致问题?

PD 我正在使用 Firebug(在 Firefox 上)来了解何时进行 SOAP 调用。

4

2 回答 2

4

同步调用会阻塞 I/O,因此不会触发警报。由于您正在等待回电,因此在此期间发生的任何操作都将被忽略。

这篇文章可能会有所帮助:http ://ejohn.org/blog/how-javascript-timers-work/

由于浏览器中的所有JavaScript 都在单个线程上执行,因此异步事件(例如鼠标单击和计时器)仅在执行过程中有空缺时才会运行。

  • JavaScript 引擎只有一个线程,强制异步事件排队等待执行。
  • setTimeout 和 setInterval 在执行异步代码的方式上有着根本的不同。
  • 如果 atimer 被阻止立即执行,它将被延迟到下一个可能的执行点(这将比所需的延迟长)。
  • 如果间隔需要足够长的时间来执行(比指定的延迟时间长),则间隔可以无延迟地连续执行。
于 2012-11-30T15:25:43.360 回答
1

因为默认情况下,UI 事件和您在 Javascript 中执行的所有其他操作都在单个线程上执行,所以您所经历的一切都是意料之中的。但这只是原因...

一旦您了解了原因,您就可以找到解决方案的一半:如果您必须进行同步 SOAP 调用,这似乎是这种情况,您将不得不为它们使用不同的线程。输入网络工作者...

要创建一个新的 Web 工作者,您调用 Worker() 构造函数,指定要在工作者线程中执行的脚本的 URI。

var worker = new Worker('my_task.js');

要接收来自工作人员的通知,请将工作人员的 onmessage 属性设置为适当的事件处理函数。

worker.onmessage = function(event) {
    console.log("Called back by the worker!\n");
};

在这里你可以找到更多:

http://en.wikipedia.org/wiki/Web_worker

引用上述来源:Safari、Chrome、Opera、Internet Explorer(版本 10)和 Mozilla Firefox 目前支持 Web Worker。Safari for iOS 5 和 Android 版本 2.0 和 2.1 支持 Web Worker。

关于 Android 支持:请参阅此处:为什么在 2.2 及更高版本中从 Android 浏览器中删除了 HTML5 Web Workers 支持?

举个涉及 IO 的例子:

https://developer.mozilla.org/en-US/docs/Using_workers_in_extensions

希望这能帮助您解决问题。

免责声明:一般来说,避免学习如何执行异步通信是很容易的,而网络工作者似乎是做到这一点的好方法。我并不是在提倡这种方法,而只是向显然别无选择的人提出解决方案。一旦您习惯了异步通信,它就会变得非常容易,并将帮助您构建更好的网站。jQuery 为异步 IO 提供了很好的支持。

于 2012-11-30T15:47:17.797 回答