2015-08-09 39 views
1

我是新來的角流星,試圖做一個類似於Reddit的應用程序來練習。但我不確定什麼是正確的訂閱和發佈方法。這是我的代碼。如何在angular-meteor上正確訂閱

angular.module('app') 
.config(($stateProvider) -> 
    $stateProvider 
    .state('boards-list', 
    url: '/board' 
    templateUrl: 'client/boards/boards-list.view.ng.html' 
    controller: 'BoardsListCtrl' 
) 
    .state('board-detail', 
    url: '/board/:symbol' 
    templateUrl: 'client/boards/board-detail.view.ng.html' 
    controller: 'BoardDetailCtrl' 
) 
) 

我想說明的/board流行後,如果你去到特定的板我想列出板上所有的帖子。

這是板名單控制器

angular.module('app') 
.controller('BoardsListCtrl', ($scope, $meteor, $modal, $log) -> 
    $meteor.subscribe('getPopularPosts') 
    $meteor.subscribe('getAllBoards') 
    $scope.boards = $scope.$meteorCollection(-> 
    Boards.find({}) 
) 
    $scope.posts = $scope.$meteorCollection(-> 
    Posts.find({}, _.defaults(DEFAULT_QUERY_OPTIONS, limit: 5)) 
) 

    $scope.getHref = (link) -> if link then "http://#{link}" else "#" 

    $scope.remove = (board) -> 
    $scope.boards.remove(board) 

    $scope.open = -> 
    modalInstance = $modal.open(
     templateUrl: 'client/common/modal-new-board.view.ng.html' 
     controller: 'ModalNewBoardCtrl' 
    ) 
) 

這是主板細節控制器

angular.module('app') 
.controller('BoardDetailCtrl', ($scope, $stateParams, $meteor, $modal) -> 
    boardSymbol = $stateParams.symbol 
    $scope.posts = [] 

    $scope.$meteorSubscribe('getBoardBySymbol', boardSymbol) 
    $scope.board = $meteor.object(Boards, symbol: boardSymbol, false) 
    $scope.$meteorSubscribe('getPostsByBoard', boardSymbol) 
    $scope.posts = $scope.$meteorCollection(-> 
    Posts.find(board: boardSymbol, DEFAULT_QUERY_OPTIONS) 
) 

    $scope.open = -> 
    modalInstance = $modal.open(
     templateUrl: 'client/common/modal-post.view.ng.html' 
     controller: 'ModalPostCtrl' 
     resolve: 
     symbol: -> $scope.board.symbol 
    ) 
) 

我的問題是,如果我寫Posts.find({}, DEFAULT_QUERY_OPTIONS)爲boardDetailCtrl的$ scope.posts,它實際上顯示所有當狀態改變時,就好像路由是/board一樣。當您直接訪問像http://localhost:3000/angular這樣的路線時,它會獲得適當的帖子。不知道爲什麼會發生這種情況,但我將其更改爲Posts.find({board: boardSymbol}, DEFAULT_QUERY_OPTIONS)然後按預期工作。

考慮到我只訂閱getPostByBoard這是關於只在給定的董事會獲得職位,我應該只能得到其中幾個。我查看了控制檯,如Posts.find({}).count(),而且令人驚訝的是它有每個帖子。

所以我的問題是我應該添加查詢甚至在我訂閱正確的發佈功能後發現?或者我在某個時候錯了?

回答

2

無論何時在Meteor開始訂閱,您都會將這些訂閱的集合添加到本地集合中。所以,如果你有一個板收集和您的主頁訂閱看到所有藏品,如:

$ meteor.subscribe(「getAllBoards」)

您將所有的板到本地收藏。在您明確停止訂閱之前,此本地集合將保持不變。因此,在您的董事會詳細信息頁面中,您仍然可以訪問該完整集合。

如果您發現您正在使用2種不同的方法進行訂閱。 $scope.$meteorSubscribe$meteor.subscribe。當$ scope被銷燬時,第一個會自動刪除訂閱。第二個將保留它。

因此,如果您想要在進入董事會詳細信息頁面時刪除集合並重新訂閱,您也可以在主頁面中使用$scope.$meteorSubscribe

這裏有一些思考的食物。如果您在主頁上,並且您使用$meteor.subscribe,那麼您已經在本地獲得了那些帖子的信息,對嗎?因此,當您點擊鏈接查看董事會詳情時,您實際上不需要再次訂閱。您可以撥打:

$scope.board = $meteor.object(Boards, symbol: boardSymbol, false); 

而且您將可以訪問該板的信息。 (我剛剛意識到你正在談論的是帖子而不是董事會,但這個想法仍然是一樣的)。

簡答:$meteor.subscribe()不會自行取消訂閱,您必須告訴它。 $scope.$meteorSubscribe會取消訂閱。

最佳做法?我將設置訂閱的選項,然後就使用find創建一個本地集合(),如:

$scope.$meteorSubscribe('getPopularPosts', _.defaults(DEFAULT_QUERY_OPTIONS, limit: 5).then(-> { 
     $scope.posts = $scope.$meteorCollection(-> 
      Posts.find(); 
    ) 
}) 

那麼你的發佈中添加的選項:

Meteor.publish('getPopularPosts', function(options) { 
    return Posts.find({}, options); 
}); 

這將限制數量帖子發送到客戶端,而不是發送所有這些信息,並且僅使用5.

當您切換到董事會詳細信息視圖時,它將不再有此信息可用於啓動您,因爲我們使用了$scope.$meteorSubscribe$scope.$meteorCollection

+0

感謝您的評論,但我有2個後續問題: 1:讓客戶端指定服務器端查詢選項作爲參數是不是非常危險?通過這種方式,他可以訪問所有帖子(即使是私人的,如果存在這樣的東西) 2:如果說Posts集合增長,並且我在其他地方有另一個訂閱與其他標準匹配的帖子,他們也會在這裏列出(因爲通配符.find()),對嗎? 預先感謝您的任何啓發;) –

+0

1.服務器端發佈方法確定允許或不允許用戶接收用戶。在這個例子中,它返回所有的帖子,但你可以很容易地添加一個你選擇的過濾器來限制用戶能夠檢索的內容。 2.通過使用meteorSubscribe,您將在更改視圖時刪除訂閱。所以只要另一個訂閱不是在同一個視圖中同時發生的,它們也不會互相阻塞。 –