2012-09-01 24 views
33

使用Meteor,我試圖瞭解何時使用服務器端Meteor.methods(),同時仍保留即時UI更新。何時使用Meteor.methods和利用存根

從安德魯Scala的introductory tutorial,他聲稱,如果要更新和修改數據庫文件Meteor.methods()應使用:

的想法是,你定義所有的服務器上做 危險的東西的功能比如修改和更新數據,然後讓客戶端 調用這些函數並獲得像常規函數那樣的返回值。客戶端永遠不會看到該實現,也不會親自修改 數據。服務器完成所有工作。

而下面這個建議,我實現了這個在我的代碼:

服務器端:

Meteor.methods({ 

    addMovie: function(data) { 
    var movie = Movies.insert({name: data}); 
    return movie; 
    }, 

    ... 

客戶端:

Template.movies.events = ({ 

    'click #add-movie': function(e) { 

    var name = document.getElementById('movie-name').value; 
    Meteor.call('addMovie', name); 

    return false; 

    }, 

    ... 

這工作,但它的速度慢。如果在客戶端調用Movies.insert(),用戶界面不會立即更新。該docs表明,糾正問題,您可以在客戶端創建存根:

在客戶端上調用方法定義具有相同名稱的 服務器方法相關聯的存根功能。如果你不想要,你不必爲你的方法定義一個存根(stub) 。在這種情況下,方法調用只是 ,就像其他系統中的遠程過程調用一樣,您將不得不等待 以獲取服務器的結果。

但是這些存根應該是什麼樣子?它應該基本上看起來與服務器端方法一樣嗎?如果是這樣,那有什麼意義?我正在尋找關於Meteor.methods()的使用和目的的更全面的解釋,存根/使用存根及其實現。

編輯: 大衛格林斯潘已經幫助澄清使用Meteor.methods()和存根meteor-talk

+1

你對戴維的回答滿意嗎?如果是這樣,只需將其作爲答案發布並接受。 –

回答

19

這裏是另一個例子。

你正在寫的賓果遊戲,並單擊該按鈕來調用「房子!」 .. Click事件可能會調用一個方法,例如

Method.call("callHouse"); 

這將調用服務器方法:

// on the server 
Meteor.methods({ 
    callHouse: function() { 
    if (currentGame.isInProgress) { 
     currentGame.winner = this.userId; 
     currentGame.end(); 
    } 
    } 
}); 

,如果你是第一個叫「家」,該方法將你標記爲贏家。但是,讓我們假裝方法極其慢,你的客戶端應用程序在等待..你是99%,確保服務器將確認你就是贏家 - 你只是想更新無需等待用戶的屏幕上。在這種情況下,實現一個客戶端存根:

// on the client 
Meteor.methods({ 
    callHouse: function() { 
    currentGame.winner = Meteor.userId(); 
    // add any other side-effects you expect to occur here 
    } 
}); 

當服務器結果返回時,如果返回的數據與您在存根中設置的數據不同,它將對其進行更正並相應地刷新屏幕。

+0

爲什麼在客戶端上使用'this.userId'和'Meteor.userId()'? – CaptSaltyJack

+0

我不記得了,幾年前我裝好流星 – Lloyd

+4

這太糟糕了。 1.0塊石頭! – CaptSaltyJack

12

簡而言之:

定義在文件中的某些方法(Meteor.methods)推到服務器,將做實際工作的服務器上,定義文件的一些方法(Meteor.methods)推到了客戶端在客戶端上的「即時」的行爲(如負載指示),直到服務器推送產生的變化返回給客戶端

這裏的大衛的原帖:

本嗨,

原則上,一種方法可以在客戶端和服務器上執行完全不同的操作,例如在客戶端上顯示加載指示符並與服務器上的遠程API交談。致電 流星。客戶端上的方法定義客戶端行爲,並且調用服務器上的Meteor.methods來定義服務器行爲 。

對於對數據庫進行操作,往往是相同的 實施,將兩種方法做。客戶端版本影響 客戶端數據庫(訂閱 至的文檔的瀏覽器端「緩存」),服務器端版本影響真實數據庫。當客戶端回聽時,它會「捕捉」到服務器端 突變的結果;客戶端數據庫突變將被丟棄(或取消對您的看法取決於 )。如果一個客戶端的方法 調用其它方法中,這些二次呼叫是遠程化到 服務器。服務器端版本將會在服務器上調用與之相同的方法,或者不會,因爲它認爲合適。

因此,您提供的任何客戶端方法impl只是一個「模擬」,並不一定是準確的(它可能無法)。希望是 ,您通常可以免費獲得模擬impl,因爲它的 與服務器impl相同!

這是回答您的問題嗎?

- 大衛

+0

謝謝Jay。一旦我有處理存根的更多經驗,我一直有意爲此寫一個後續答案。我最終可能會這樣做,但現在我會接受你的答案。 – bento

+0

@jay,對於客戶端和服務器(外部客戶端和服務器文件夾)使用一種方法是否具有相同的效果? – securecurve

+2

Hi @securecurve 存根僅用於客戶端的即時更新,一旦服務器執行操作並返回,其結果將被覆蓋。 例如,如果您的客戶端上有upVote方法,您可以在投票中加1,然後更新UI,但同時Meteor會在服務器上調用相同的方法(可能會也可能不會返回相同的結果,如果其他人投票舉例) – jay

3

如果定義由客戶機/服務器像/collections共享文件的方法,豈不是既方便和自動存根?

所以:

/collections/houses.js

Meteor.methods({ 
    callHouse: function() { 
    if (currentGame.isInProgress) { 
     currentGame.winner = this.userId; 
     currentGame.end(); 
    } 
    } 
}); 

這將是提供給客戶端和服務器。如果它沒有通過,服務器將自動拒絕客戶端更新/恢復它。

+0

安全嗎?因爲用戶有權訪問代碼 –

+0

是的,您可以使用流星安全規則。 –

+0

@BrunoLemos我在開始時也有這種擔憂,但Meteor背後的部分設計原則是它到處都是數據庫,所以您可以使用相同的方法從客戶端和服務器訪問數據庫。客戶端可以訪問代碼並不重要,因爲無論客戶端是什麼,服務器端都會一直驗證。 – d4nyll

3

正如丹尼爾說,你可以在一個文件中定義的方法,它不是在客戶端或服務器的目錄和可在兩側。您還可以使用isSimulation布爾值進行其他檢查。例如,它可能看起來是這樣的:

Meteor.methods({ 
    addMovie: function (movieData) { 
    if (!this.isSimulation) { 
     check(movieData, someAdditionaCheckinFunc); 
    } 
    Movies.insert(movieData); 
    } 
}) 

因此,在條件分支的代碼將僅在服務器上執行。