Page 37 - JavaScript修炼之道
P. 37

24       第二部分  DOM、事件及定时器


             任务 11  模拟后台处理


                 有时,你会需要在网页里进行一个相当耗时的处理,比如,从一个表中得到一个数据集,经
             过各种计算(可能需要相当长的时间),最后得到一个图表。你希望在这个过程中页面仍然能够
             得到正常的响应,这就需要用到后台处理技术。

                 这是因为JavaScript引擎会以如下方式执行你的代码。

                   JavaScript本质上是单线程的。
                   你的JavaScript运行线程实际上和你的页面共享了同样的资源。这也意味着,当你的
                   JavaScript代码运行的时候,任何页面渲染都不会发生。新的内容不会出现,内容无法重
                   排,甚至被其他窗体所遮挡的页面也无法被重绘……总之,什么都不能做。

                 所以,如果你的页面在执行一些密集的计算,那么直到处理结束前页面都不会有响应。这通
             常意味着整个浏览器都会失去响应。为了防止出现这种情况,一些浏览器提供了“中断运行时间
             过长的脚本”的功能。而其他浏览器,例如Chrome,则会为每个页面开一个独立的进程,以处
             理这个问题。

                                      ①
                 如果不使用Web Workers (至少现在来看,这显然不是一个跨浏览器的选择)的话,你就需
             要使用一些伪并行处理的技巧,此类技巧一般依赖于全局window对象提供的一对方法——
             setTimeout()和clearTimeOut() 。

                 这些技巧的思路是把一个大型任务分解成若干个小步骤,然后一边执行这些步骤,一边记录
             任务的进度,并在固定的时延对这些步骤进行调度。当一个步骤完成之后,经过一段时间再启动
             下一个步骤。在这段空闲的时间里,浏览器会恢复对页面的控制,因此就可以正常地处理页面行
             为,并运行其他待执行脚本。

                 虽然调用clearTimeout()来清理调用setTimeout()时所存储的定时器处理器并不是必需
             的,但这是一个良好的编码实践,它可以减少内存的消耗,而且不会带来多少性能上的开销。

                 尽管这个技巧适合用于密集计算处理任务,但是它并不适合那些需要平滑过渡的行为,比如

             视觉效果,因为定时器的精度很差(在25ms~500ms变化)。在这种情况下,你需要使用一个具有
             精确固定间隔的定时器 。
                                 ②
             ——————————
                ①  详见http://en.wikipedia.org/wiki/Web_worker。*
                ②  如果想要了解具体的实现方式,请阅读Thomas Fuch编写的这个50行的绝妙程序Émile:http://github.com/madrobby/
                   emile。
   32   33   34   35   36   37   38   39   40   41   42