使用 Meteor 輕鬆開發實時網站

發表於2013-03-15

來源:IBM Developerworks

簡介: 由於 Web 無處不在,即便是很小的資料交付延遲都有可能刺激到使用者。他們希望資料即時更新。不幸的是,Web 技術無法實現這種實時訪問。儘管資料訪問正快速標準化為一些物件關係對映 (Object-Relational Mapping, ORM) 模型,但實時通訊沒有任何類似的解決方案。本文將討論 Meteor,這是一個旨在解決此問題的激動人心的新 JavaScript 框架。

什麼是 Meteor?

Meteor 是一種新的 JavaScript 框架,用於自動化和簡化實時執行的 Web 應用程式的開發。它使用一個名為分散式資料協議 (Distributed Data Protocol, DDP) 的協議來處理實時通訊,使用 WebSockets 的新瀏覽器以及使用 Asynchronous JavaScript + XML (Ajax) 長輪詢的舊瀏覽器來支援這種協議。在這兩種情況下,瀏覽器到伺服器的通訊是透明的。

DDP 協議旨在處理 JavaScript Serialized Object Notation (JSON) 文件集合,使 JSON 文件容易建立、更新、刪除、查詢和訪問。因為 DDP 是一種開源協議,所以您可將它連線到任何客戶端或資料儲存。它為 MongoDB 提供了開箱即使用支援。

事實上,Meteor 提供了兩個 MongoDB 資料庫:一個客戶端快取資料庫和伺服器上的一個 MongoDB 資料庫。當一個使用者更改一些資料時(例如通過單擊 Save),在瀏覽器中執行的 JavaScript 程式碼會更新本地 MongoDB 中的相應的資料庫項,然後向伺服器發出一個 DDP 請求。該程式碼立即像操作已獲得成功那樣繼續執行,因為它不需要等待伺服器回覆。與此同時,伺服器在後臺更新。如果伺服器操作失敗或返回一個意外結果,那麼客戶端 JavaScript 程式碼會依據從伺服器新返回的資料立即進行調整。這種調整稱為延遲補償,向使用者提供了更高的認知速度。

顯然,甚至連 Meteor 的模板系統也是為簡化實時通訊而設計的。在大多數 Web 框架中,您可以輕鬆地混合使用超文字標記語言 (HTML) 和程式碼,或者與 HTML 等效的標記,比如 HTML 抽象標記語言 (Haml)。這使您能夠輕鬆地將來自資料庫的動態值插入傳送給使用者的頁面中。在這之後,您應該負責準備提供一個系統來觀察對資料的更改,然後更新您的標記。但是,Meteor 中的模板系統用於記錄訪問了模板中的哪些資料,並自動回撥,以便在底層資料更改時呼叫此 HTML,使實時模板變得更加簡單快捷。

示例:連結流行度競賽

Meteor 的模板功能可使眾多實時應用程式更容易編寫。例如,假設您希望建立一個的站點,使用者可在其中輸入連結(即統一資源定位符,URL),並投票肯定和否決它們,而且贏得流行度競賽的 URL 會顯示在一個列表頂部。通過使用 Meteor,您可以輕鬆地實時編寫這樣一個應用程式,以便使用者可在其他使用者投票時看見他們的 65 張選票。

安裝 Meteor

要安裝 Meteor,可以將 清單 1 中所示的程式碼鍵入到一個 Linux® 或 Mac OS® X 終端中。Meteor 不支援 Microsoft® Windows®。

清單 1. 安裝 Meteor

現在您可建立一個新專案。

建立一個新專案

meteor 命令可自動化包含新專案建立過程中 Meteor 需要操作的一切內容的。鍵入 清單 2 中所示的命令,以便建立一個名為 realtime_links 的專案。

清單 2. 建立您的 Meteor 專案

Meteor 建立了一個目錄,其中包含一個 HTML 檔案、一個 JavaScript 檔案和一個級聯樣式表 (CSS) 檔案。最後一個檔案是一個標準 CSS 檔案,但前兩個值得討論一下。您可以從 下載 一節下載 realtime_links.html 和 realtime_links.js 檔案的完整版本。

realtime_links.html 檔案

清單 3 顯示了 realtime_links.html 檔案的標頭和正文片段。

清單 3. realtime_links.html 標頭和正文片段

可以看到,HTML 模板的開頭非常簡單。無需擔憂如何包含 BODY 標記、DOCTYPE 修飾符甚至 JavaScript 和 CSS 檔案。Meteor 會為您處理所有這些操作。有關 Meteor 的 JavaScript 和 CSS 包的更多資訊,請參閱 參考資料,獲取 Meteor 網站的連結。

{{> 語法表示 “呈現此模板”。可以看到,realtime_links.html 呈現了 3 個模板:

  • header 是一個簡單頭部,顯示了資料庫中的連結數量。
  • link_list 顯示了連結的列表和它們的相關投票。
  • add_new_link 是新增新連結的表單。

清單 4 顯示了 header 模板。

清單 4. realtime_links.html header 模板

header 模板呈現了一個 h1 標記以及對集合大小的簡短描述。collection_size 方法是在 JavaScript 檔案 realtime_links.js 中定義的(這將在 下一節 中詳細討論)。Meteor 自動觀察某個模板插入了哪些資料片段。所以,在更新集合大小時,header 模板會自動更新。

請注意,這裡使用的 {{ ... } 語法類似於 Ruby on Rails 中的 <%= ... %> 或 PHP 中的 <?= ... ?>。它可插入任意程式碼,所以能夠以這種方式插入任何有用的動態表示式。

清單 5 顯示了 link_list 模板。

清單 5. realtime_links.html link_list 模板

如您所見,清單 5 中的程式碼是一個連結列表。realtime_links.js JavaScript 檔案中的 links 方法提供了此列表。系統會向每個連結呈現link_detail 模板。請注意,無需傳遞任何引數,因為 Handlebars 的 #each 迴圈會將每次迭代的當前上下文設定為當前物件。換句話說,會將 link_detail 模板的本地方法正確解釋為每個連結物件的方法。

清單 6 顯示了 link_detail 模板,它控制了為每個連結顯示的資料。

清單 6. realtime_links.html link_detail 模板

h1 元素簡單地顯示當前連結的 URL。然後會提供一個間斷的統計清單,其中包含一個連結被支援的次數、被否決的次數和它的淨分數(也就是兩個值的差)。最後,有兩個按鈕:一個用於投贊成或支援票,另一個用於投反對或否決票。JavaScript 檔案定義這些按鈕的行為,但是在深入介紹此主題前,還有一個模板需要了解。

清單 7 顯示了 add_new_link 模板。

清單 7. realtime_links.html add_new_link 模板

該模板只是一個文字輸入欄位和一個按鈕,它們共同形成了向您列表中新增新 URL 的介面。

realtime_links.js 檔案

realtime_links.js 中的 JavaScript 程式碼控制來自您程式的資料訪問和事件回撥,無論是在客戶端還是在伺服器上。if (Meteor.is_client) 語句用於標記客戶端部分,if (Meteor.is_server) 語句用於標記伺服器部分。Meteor 提供了一種保護敏感程式碼的方式,阻止惡意客戶端看到原始碼。參見 參考資料 中的 Meteor 文件連結,瞭解有關的更多細節。

清單 8 顯示了標頭和連結列表幫助器函式。

清單 8. 標頭和連結列表幫助器函式

header 模板使用清單中的第一個幫助函式,該函式返回 links 集合的大小。link_list 模板使用第二個幫助器函式,它返回從最高分到最低分排序的所有連結。

清單 9 擁有對 link_detail 模板的兩個事件回撥。

清單 9. link_detail 事件回撥

每個事件回撥處理一個支援或反對單擊事件。在每種情況下,它們使用客戶端上的 Meteor.call 在伺服器上執行一次函式呼叫。可以看到從客戶端對伺服器執行呼叫很簡單。例如,序列化會自動處理。

清單 10 顯示了對使用者可新增新連結的表單的事件回撥。

清單 10. 對新增新連結表單的事件回撥

首先,該表單會嘗試找到一個具有所請求 URL 的現有連結物件。如果它找到這樣一個物件,那麼它會將該請求統計為對這個現有連結物件的一次投票。如果未找到,那麼它會建立一個新連結物件,並對這個新物件執行一次 thumbs_up 投票。

這部分程式碼演示了 Meteor 作為一種一流技術的優點和不足,它還不適合用於生產。如您所見,客戶端可在 links 集合上呼叫insert。儘管這對開發人員很有用,但從安全形度講,這是一個問題。幸運的是,開發人員正在積極研究該程式碼的一個 auth 分支,這個分支可以實現強大的身份驗證功能,同時仍然保持 Meteor 富有吸引力的很多強大功能和靈活性。

此外,需要認識到 Meteor 目前沒有實現所有 MongoDB 功能。例如,Meteor 不支援 MongoDB upsert,該操作插入新資料或修改舊資料。如果 Meteor 支援 upsert,那麼您可以編寫 清單 11 中所示的函式。

清單 11. 一個使用 upsert 的假想的新增新連結表單事件回撥

如您所見,使用 upsert 的程式碼更短。它執行得可能更快,因為它僅需要與伺服器執行一次往返傳輸。如果順利的話,Meteor 很快就會實現對 upsert 和其他新功能的支援。

清單 12 中的程式碼在伺服器上執行。它是一個可由客戶端程式碼呼叫的方法。此方法(vote)允許客戶端對一個流行的 URL 投thumbs_up 或 thumbs_down 票。它使用 Mongo 的 $inc 運算子遞增適當的投票計數器。它還在必要時遞增或遞減總數。Meteor.startup 方法僅支援程式碼在伺服器啟動時執行。Meteor.methods 函式然後定義可在客戶端上呼叫 Meteor.call 的函式,如前面的 清單 9 中所述。

清單 12. 伺服器端的 vote 方法程式碼

與 清單 10 一樣,您可在客戶端上執行 清單 12 中的程式碼。但是,出於演示目的,將會在伺服器上執行該程式碼。隨著 Meteor 的安全模型得到改進,可能會將敏感的程式碼開發為伺服器端函式,如下面清單所示。

檢視您的應用程式的實際效果

現在可啟動您的 Meteor 應用程式(如 清單 13 中所示)並檢視它的實際效果。

清單 13. 啟動您的系統

在啟動後,Meteor 會在埠 3000 上執行。開啟一個 Web 瀏覽器並訪問 http://localhost:3000/。

如果在 Add a URL 下輸入一個 URL 並單擊 Add,則看到一個 URL 和評分 one。然後您可以單擊 Thumbs Up 或 Thumbs Down 按鈕對該 URL 進行投票。這會實時進行,而不會重新整理頁面。如果開啟一個新 Web 瀏覽器,可在另一個視窗中執行相同操作,這時第一個視窗會立即更改。

當新增多個 URL 時,可以看到一個具有最高評分的 URL(分數被定義為支援票數減去反對票數)顯示在最頂部。在投支援或反對票時,URL 會隨著其評分更改而在列表中向上或向下移動。這是實時進行的,在輸入投票時,多個瀏覽器上的多個使用者都會收到相同的資料。

結束語

Meteor 是一個極具優勢的 Web 框架,它包含了許多有趣的概念。它對實時資料的支援既富有吸引力又至關重要,特別是在考慮到其他技術實時支援充其量是一種事後行為時。隨著實時互動變得對未來的 Web 更加重要,Meteor 輕鬆快速地實時處理複雜資料集的能力也將變得更加重要。

相關文章