實時開發框架Meteor API解讀系列Publish and Subscribe-(2)

寫在前面的話

  1. 該篇博客承接上一篇博客。
  2. 該博客寫的當天,Meteor 0.8.0發佈,改動比較大,因爲從本篇博客開始使用0.8.0版。由於本人對新版本沒有實戰開發,因此會有描寫不到位的地方,忘諒解。
  3. 本篇博客僅爲參考。更多細節請閱讀官方文檔。

publish 回調函數中 client端傳遞過來參數的使用。

接着上一篇博客的源代碼:

publish.js

Meteor.publish("people", function (random) {
//接收從客戶端傳過來的參數random。這裏讓參數爲一個50以內的隨機整數。根據不同的值,返回不同的結果集
//這裏只是對參數的簡單使用,更靈活的使用可以根據實際情況來。比如將參數作爲數據集查詢條件等。
    console.log(random);
    if(random<30){    
        return PeopleCollection.find({},{limit:1}); //如果客戶端傳過的參數小於30則只返回一行結果,下面的意思一樣,分別是3,5個數據  
    }else if(random>30){  
        return PeopleCollection.find({},{limit:3});    
    }else{  
        return PeopleCollection.find({},{limit:5})  
    }  
}); 

subscribe.js

//隨機傳遞一個隨機數 這個隨機數可以根據實際換成相關的活性數據源,每次數據源發生變化,這個數據集合就會重新獲取。
//個人建議:當數據集合過大時,不要經常改變 數據集的限制條件(傳個服務端的),這樣會造成比較大的網絡開銷,尤其在網絡環境不好而且數據量比較大的情況下,會出現一些意向不到的情況。
Meteor.subscribe("people_safe",Math.floor(Math.random()*10)*5,function(){
    console.log("數據訂閱完成");
    //獲取數據後打印  服務端發送過來的數據集
    console.log(PeopleCollection.find({}).fetch());
});

現在啓動服務器。打開瀏覽器 訪問localhost:3000,打開瀏覽器控制檯。可以看獲取的的數據集合。每次刷新瀏覽器,數據都可以不同。

publish 回調函數中 內置參數的使用。

根據官方文檔介紹,內部參數主要有以下幾個

this.userId
this.added(collection, id, fields)
this.changed(collection, id, fields)
this.removed(collection, id)
this.ready()
this.onStop(func)
this.error(error)
this.stop()
this.connection

下面將有選擇的 對上面的函數進行代碼示例說明。

this.userId

當你使用了 包 Accounts 後,存在用戶登錄管理,該字段有效。 
這個字段表示當前的用戶id。當用戶id改變時,meteor將重新推送數據。因爲目前沒有涉及到包的使用。那麼這裏只是對它進行簡單的代碼說明。以後如果講到Accounts的使用後,讀者自會明白怎麼樣有效使用它。 
(ps:下面這段代碼不會出現在 供下載的源碼包裏。)


Meteor.publish("people_safe", function(){
    //通過使用this.added函數進行數據的重寫改寫。這裏爲數據對象增加一個 testAdded 字段

    //避免this 在內部回調函數中的混淆使用,重新引用到self 個人建議:在需要使用this儘量使用其他變量代替。
    var self = this;
    var beforeList = PeopleCollection.find({}).fetch();
    console.log(beforeList);//在服務端打印未修改之前的數據

    //修改數據
    //注意這樣的修改不會個改變原始數據,也就是它只是一個臨時數據的集合,經過了一定程度的加工而已,不會實際影響到數據庫裏面的數據,
    //你只要刷新瀏覽器,在看看服務端的打印就可以了明白。
    PeopleCollection.find({}).forEach(function(item){
        item["testAdded"] = true;
        //注意這裏的第一個參數一定要和conllection.js裏面定義的一致,
        //不然的話 前臺無法獲取數據,因爲PeopleCollection是關聯的people數據集的。
        //可以看成self.added方法的調用,申請了一個'假的'數據集(沒有對實際數據庫裏面的數據進行任何修改)
        //這一點可以在啓動系統打開瀏覽器後,連接mongodb進行查看原始數據。
        //當然瀏覽器端對數據增刪改還是會影響數據庫裏面的數據的,因爲該self裏面的數據副本的_id和原始數據_id一致,
        //而且前臺對數據的修改也是根據_id來的。
        self.added('people',item._id,item);
    });
    //self.ready表示 數據已經準備完畢,可以推送到客戶端了。
    self.ready();
    //注意 和以前的使用方法不一樣,這裏沒有return,要返回的數據都包涵在self裏面了。

});

修改後的subscribe.js:

Meteor.subscribe("people_safe",function(){
    console.log("數據訂閱完成");
    //獲取數據後打印  服務端發送過來的數據集
    console.log(PeopleCollection.find({}).fetch());
});

啓動應用,打開瀏覽器控制檯。刷新頁面 觀察代碼效果。

看到數據打印後,來證明一下,前臺瀏覽器的數據修改對數據庫有效。

首先在瀏覽器端獲取一個數據對象,在控制檯輸入:

console.log(EJSON.stringify(PeopleCollection.findOne()))

會看到類似下面的結果:

{"_id":"CEuSX5JGTFF9w8fvr","name":"小A","address":"長沙","phone":"111","testAdded":true} 
這裏把注意,_id的值你的和我的不同,因爲這個是隨機生成的標識符。

輸入:注意輸入 你控制檯上對應_id 而不是拷貝我的。

PeopleCollection.update("CEuSX5JGTFF9w8fvr",{$set:{name:"小A-AddTest"}})

如果你的update第一個參數_id沒有填寫錯誤,那麼應該是修改成功了。

好,現在來看一個比較神奇的現象。

重新運行

console.log(EJSON.stringify(PeopleCollection.findOne()))

發現一個有趣的現象,打印的結果是:
{"_id":"CEuSX5JGTFF9w8fvr","name":"小A","address":"長沙","phone":"111","testAdded":true}

和沒有修改數據之前是一樣的!!

(注意保持Meteor服務器開啓,新開一個shell或者cmd窗口)
接着我們看看數據庫中數據是否發生了改變,以下爲shell命令(CMD命令也是一致的)
假設API-003是應用目錄。

cd API-003
meteor mongo
use meteor
db.people.find()

會發現數據集中一個數據的name字段確實改變了。(但是testAdded字段沒有,因爲說過,testAdded字段只是出現在當前副本數據,不影響數據庫)

其實我們只要刷新一下瀏覽器,也可以看到修改後的結果。
那麼得出一個結論:

通過this.added 修改後的數據是數據庫的一部分副本,在服務端該副本不對數據庫產生影響。
當在瀏覽器端,對對於的數據集對像進行操作時,數據會影響到數據庫,但是不會使本地數據副本更新,那麼可以認爲該數據副本是沒有活性的。也就是不會同步到其他客戶端,後臺數據的變化也不會影響到當前瀏覽器端的這個副本。

上面這段話可能表述不是很清楚,但是代碼的結果可以很好的解釋這個this.added的作用。
this.changed(collection, id, fields) this.removed(collection, id)

這兩個函數的作用 各位可以根據added的代碼 進行相應的測試,這裏不再表述。它對數據集的影響和added一致。 源碼中將會貼出這部分代碼。就不再博客裏面贅述了。

源代碼地址:https://github.com/huyinghuan/Lesson/tree/master/Meteor/API-003

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章