jQuery Deferred Object

jQuery 的 .ready() 有兩個特性,一是可以丟多個函式進去,它會照順序執行,第二個就是如果文件已經讀完,還丟函式進去的話,變成會馬上執行,這兩個特性讓 .ready() 變得非常好用,寫程式寫到有需要在頁面讀完才執行的東西,隨時都可以丟個函式進去,不過同樣是讀取資料下來,ajax 的 request 卻沒辦法做到一樣的事情,只能使用 callback ,所有要做的事情都要一次指定好,侷限了程式的結構設計。

jQuery 1.5 的幾個新功能中,有一項特別吸引人注目的,就是 deferred 物件 這個新的物件兼行為,我剛開始看文件時,一直不能了解為什麼要設計這個物件和設計它這樣的行為,直到我遇到前一段的問題時才整個豁然開朗, jQuery 1.5 把 ajax 改寫,其中一項變化就是回傳的值從 XMLHttpRequest 變成 jqXHR 物件,而這個 jqXHR 物件其實就是個 deferred 物件,deferred 物件用來代表某件事情,我們可以用來設定該事情的結果是否成功,並且根據不同的結果要做哪些事情,程式執行到可以判斷這個 deferred 物件代表的事件是成功的話就執行 resolve(),deferred 物件會把它所知道,事情成功的話要做的事情照順序做過,失敗的話就執行 reject(),一樣 deferred 物件會把失敗時要做的事情做一遍。而在事件結果確定之後,deferred 物件還是可以繼續接收函式,只是就像.ready()一樣,會變成馬上執行(或是直接丟掉不裡)。而 jqXHR 物件本身就代表 XMLHttpRequest 這件事情,request 的結果就是 jqXHR 的結果,它會在 request 成功的時候 resolve,失敗的時候 reject,換成這樣的架構後,做 ajax 變成可以在任何時間丟入複數的 callback,再也不用在建立 request 的時候就把需要的 callback 都準備好,使用上整個方便很多,程式的架構也因此可以變得更自由。

而除了 ajax 相關的函式之外, jQuery 也提供函式可以產生空白的 deferred 物件,然後程式設計師可以自己設計它代表的事件以及其行為,相信這個新的設計可以讓 jQuery 的 plugin 開發變得更簡單,基本上非同步的東西都可以使用 deferred 物件,我想應該不少的使用者行為可以用 deferred 物件來重新設計並且有更好的架構才是。


Gundo.vim

Gundo

詳細可以看 Vimcast 最新的一期:Undo branching and Gundo.vim,簡單說就是 Vim 有個 undo branch 讓你 undo 後又做了修改後,還可以回到原來 undo 前的版本,不過標準的操作方式並不好用,甚至很多人都不知道有這個功能,因此 Steve Losh 做了個 Gundo ,讓 undo branch 圖形化,並且可以直接移動到特定的版本,實在是非常強大,還在開發的時候我就一直很注意了,沒想到忘了一陣子,它就已經發展到 2.0 了,總之看到後馬上就變成必備的 vim plugin 了:P。


DOM Range, IERange, rangy

有在接觸 JavaScript 編輯器的比較會遇到這問題,就是如何存取、甚至修改使用者選取的文字,按照標準的話,應該是使用 DOM 的 Range ,不過一如往常,IE 不支援,預計是 IE9 才會有正式的支援,而之前的版本則是用他們自己的 TextRange ,基本上,TextRange 這個標準還蠻難懂的(意思就是我也還沒能了解),然後總之就是不好使用,所以就有了 IERange 這個函式庫,利用 TextRange 實作了 W3C 的 DOM Range ,而且發展蠻久了,還蠻可靠。

不過 IERange 還有一個問題沒辦法解決,就是輸入欄位如 input 和 textarea 內,文字選取狀態的存取,現在大部分瀏覽器都是支援selectionStartselectionEnd這兩個屬性和setSelectionRange(),標準是定在 HTML5 的 text field selections API 裡面,IE 的話則是要使用上面提到的 TextRange 來存取,而且實際上操作也沒很簡單,所以也有位 Tim Down 弄了 rangyinputs 這個 rangy 的簡化版,專門針對跨瀏覽器、文字輸入框的選取所做的函式庫,也有包好的 jQuery Plugin,我看 Stack Overflow 上不少篇相關的問題都有人推薦 rangy (作者本人的推薦也不少XD),實際上下去並測了一下還沒有遇到什麼問題,雖然功能上沒什麼問題,不過還是有些地方有些可惜,就是它的 API 沒有跟著 HTML 標準,然後沒有文件,所以要怎麼用要自己看原始碼,另外我覺得有一些地方設計似乎不是很好,像是getSelection()會傳回 range 物件,但是setSelection()卻不能直接把 range 物件送進去,要把選取的開始和結束兩個直分成兩個參數丟進去,不過相較於要跟 TextRange 打交道這檔事,這些缺點根本就是優點啊!


更之前的文章