Non-blocking Web UI:不會卡的UI

之前做Project時碰到很嚴重的Blocking問題,剛好看到Spine.js作者的這篇

Asynchronous UIs - the future of web user interfaces

這篇點出了一個pattern: 我們設計的UI很多時都是”click-and-wait” (點擊與等待),而User是討厭等待的生物…所以AUI應此而生。

而AUI的基本,是Non-blocking -

  1. 即使有大量JS Event或運算,網頁仍然有能力回應User的UI Event (mouse click之類)。
  2. 沒有該死的會鎖死整頁的progress bar/spinner但同時仍然有progress可見,User在等的時候仍然有事可做又不會誤會”thing is done”而關了網頁

2基本上是設計,然而1是技術-因為Browser對網頁JS的處理形式一不留神就會出現Blocking (輕則click沒反應,重則會出現沙漏/彩球):

  1. JS processing是Single-thread (和Java早期GUI只有一條main-thread有點像) [0]
  2. 一般而言JS運算很快^,除以下幾個情況:
    • DOM Operation (document.*, element.*) [1]
      (所以jQuery的animation是慢到不行的東西,動態HTML元素生成及附加也是)
    • eval, with, for-in [2]
    • JSON Parsing & Stringfity [1] (webkit-only)
    • XMLHttpRequest [1]
    • jQuery的Event處理 (jQuery 1.7的.on() & .off()就是為了修理這件事…) [3]
    • 特定function組合 - e.g. setTimeout()/setInterval()內有requestAnimationFrame() [4]
    ^1 一般是指event handler在3年以內的Desktop的modern browser (FF4+,IE 9+,chrome 10+,safari 4+) 是100ms以下完成, 幾乎感覺不到 - 所以desktop上運行順暢的重型script在mobile上可能會卡死
    ^2 jQuery的可是結結實實的碰過釘啊…
  3. 以上種種情況一旦沒控制好皆可能會出現Blocking,而解決Blocking不外乎是yielding & threading
    • threading: JS只有兩種情況下可以開thread,Web Worker或是XHR。不過前者不能做DOM Operation而後者會開Network connection會增加Browser負擔(所以慢),應用範圍有限。
    • yielding: 簡單說就是強行留cpu time給browser處理UI Event。Yielding基本上可以透過setInterval、setTimeout和setImmediate達成,詳見
      用 setInterval 防止瀏覽器卡死
      Script yielding with setImmediate
      *要說yielding會有甚麼問題,主要問題在電量和Timer resolution之分歧上-各個browser+OS對”0 delay”的定義可是毫不一致,4ms ~ 16ms都有。

如果不做threading/yielding又要UI不卡,一要CPU夠力,二要GPU對某些功能有硬體加速** (iOS/webkit上的CSS3硬體加速,各大browser對canvas/webGL以至SVG的硬體加速等),然而這樣做一到mobile可以死的非常慘-是以慎重的處理程式內的Event及DOM操作-event handler有沒有call stopPropagation()、對吃cpu的後續動作加上yielding是很重要。

…要是早一點知道Spine.js也許就不會那麼血淚了 :(

(又,Mobile Browser是面很好的照妖鏡或code breaker…)

**有硬體加速和沒有的分別在?用有硬解的機器(iPad/iPhone)和沒硬解的機器(netBook)看720p的mp4片子就知道了…cpu用量(=機器表面溫度)差超多的。

Off-Topic: 為什麼JS Processing會是Single thread?
因為曾經有個叫Safari 2.0的傢伙試行multi-thread (全部script node multi-thread同時執行),結果死很大,因此沒有一家敢用multi-thread了。(也可能是Spec在有人如此胡來後改了也說不定)

Tags: js WTF webdev