用 setInterval 防止瀏覽器卡死

Twitter 上面的 vincicat 發問

@timdream 咦,這個沒聽過,setInterval是怎樣避免block UI?

其實這個技巧我已經忘記是哪裡看到,還是小時候自己試出來的。總之,如果要重複進行一個會讓瀏覽器卡住的計算或是 DOM Operation,可以考慮不要用原本的 forEach、for、或是 while,改用以下的 pattern。

原本的:


arr.forEach(
    function (val, key) {
        [昂貴 DOM 運算,例如畫 canvas,塞 element ...]
    }
);

可以換成


var i = arr.length-1;
timer = setInterval(
    function goNext() {
        [昂貴 DOM 運算,例如畫 canvas,塞 element ...]
        if (!i--) {
            clearTimeout(timer);
        }
    },
    0
);

或是,如果在意順序的話:


var i = 0;
timer = setInterval(
    function goNext() {
        if (i >= arr.length) {
            clearTimeout(timer);
            return;
        }
        [昂貴 DOM 運算,例如畫 canvas,塞 element ...]
        i++;
    },
    0
);

因為瀏覽器的 UI 是 single thread queue,在網頁的 Javascript 執行完之前瀏覽器是沒有辦法做其他事的。不過用了這個 pattern,我的猜想是即便程式碼是 0 ms 的 setInterval,在迴圈兩個元素執行之間瀏覽器會有機會 queue 自己的工作,因此 UI 可以保持有回應的狀態(例如,使用者可以按 Ctrl+F5 reload)。

當然真的需要花時間的計算要丟進 Web Workers 才對啦,但我自己的經驗是有支援 Web Workers 的瀏覽器速度都夠快 … 根本就用不到 Web Workers。而且真正會卡的東西都是 DOM Operation,Web Workers 不能用。雖說整個迴圈執行的總時間會加長,但是體驗上比較 OK;瀏覽器把每個步驟的 DOM 改變都呈現出來有時會有意想不到的視覺效果 :)。

這是最近寫某個玩具的心得,stay tuned for announcement。

專訪 Mozilla 總部

去年 12 月去了 San Francisco,順道去參觀了 Mountain View 的 Mozilla 總部(感謝 Marketing 的 Mary Colvig 的招待!)。我自己在當天例會給了 5 min 的小 talk 介紹了 MozTW,反過來則邀請了四位 Mozilla 的員工讓我訪問,影片在 YouTube 上

如果有時間的話,請到 Universal Subtitles 幫忙上字幕!感謝!

WordPress Subversion Install/Upgrade Script

不值得大張旗鼓的小東西,不過既然貼出來了就介紹一下。

wp-script:WordPress 安裝/升級用 shell script

以前就用 shell script 管 WordPress 的安裝與升級,不過後來發現這樣用蓋 tarball 的方式放檔案會讓舊檔案一直被留在機器裡。所以後來就直接拉 WordPress 的 subversion 程式庫裡的檔案跑 svn switch,直接跳到需要的版本的 tag。這組 script 又額外加上了和 API 溝通,直接問 WordPress.org 最新的版號,所以執行起來又更方便。建議的使用情境是看到 WordPress 有更新的新聞就連進去執行備份+更新。不建議在不做自動備份的情況用 crontab 自動更新。

至於中文檔案的部分,script 加上了 subversion 的 external reference ,會去抓 Kirin_Lin 維護的 WordPress 中文翻譯(放在 automattic 那邊)。不過,他有時候無法在緊急更新的時候把版號 tag 即時 commit 到中文程式庫(有時候也沒有必要,因為介面沒有修改),這個時候 script 找不到該版號的目錄就會去抓 trunk。

用文字描述程式行為有點難懂,歡迎直接去看 source code =) 接下來應該會寫幾個單鍵更新外掛和佈景的 script 放進去,一樣也是會自動查版號。