-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy path04s-publications-and-subscriptions.md.erb
220 lines (137 loc) · 13.8 KB
/
04s-publications-and-subscriptions.md.erb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
---
title: Publications et Souscriptions
slug: publications-and-subscriptions
date: 0004/01/02
number: 4.5
points: 5
sidebar: true
photoUrl: http://www.flickr.com/photos/ikewinski/11264732804/
photoAuthor: Mike Lewinski
contents: Comprendre comment les publications et les souscriptions fonctionnent.|Apprendre le comportement par défaut du paquet autopublish.|Voir quelques exemples de patrons de publications.
paragraphs: 52
---
Publications et souscriptions sont un des concepts les plus importants et fondamentaux dans Meteor, mais peut être difficile à se représenter quand on débute.
Cela a conduit à beaucoup d'incompréhensions, telles que Meteor n'est pas sécurisé, ou que les applications Meteor ne peuvent pas gérer une large quantité de données.
Une grande part de la raison pour laquelle les gens trouvent ces concepts un peu perturbants est la "magie" que Meteor fait pour nous. Bien que cette magie est d'une aide considérable, elle peut obscurcir ce qui se passe vraiment en arrière-plan (comme la magie a tendance à le faire). Détaillons un peu les couches de magie pour essayer de comprendre ce qu'il se passe.
### Les vieux jours
Mais dans un premier temps, regardons en arrière dans les vieux jours de 2011 quand Meteor n'était pas encore là. Disons que vous développez une simple application Rails. Quand un utilisateur atteint votre site, le client (i.e. votre navigateur) envoie une requête à votre application, qui est en cours sur votre serveur.
Le premier travail de l'application est de trouver quelles données l'utilisateur a besoin de voir. Ça pourrait être à la page 12 de vos résultats, les informations de profil de Marie, les 20 derniers tweets de Bob, etc. Vous pouvez imaginer un marchand de livres recherchant dans des allées le livre que vous avez demandé.
Une fois que les bonnes données ont été sélectionnées, le second travail de l'application est de traduire ces données dans un joli HTML lisible par un humain (ou en JSON dans le cas d'une API).
Dans la métaphore du marchand de livre, vous pouvez envelopper le livre que vous venez juste d'acheter et le mettre dans un joli sac. C'est la partie "vue" du fameux modèle MVC (Model-View-Controller).
Finalement, l'application prend du code HTML et l'envoie au navigateur. Le travail de l'application est terminé, et maintenant que toutes ces choses sont sorties de ses mains virtuelles, elle peut se détendre avec une bière et attendre la prochaine requête.
### La vision Meteor
Regardons ce qui rend Meteor si spécial en comparaison. Comme nous l'avons vu, l'innovation clé de Meteor est que là ou l'application Rails vit seulement **sur le serveur**, une application Meteor inclut également un composant côté client qui va s'exécuter **sur le client** (le navigateur).
<%= diagram "client-server", "Envoyer un sous-ensemble de la base de données au client.", "pull-right" %>
C'est comme un marchand qui non seulement vous trouve le livre, mais aussi vous suit jusque chez vous pour vous le lire au moment de dormir (ce qui peut paraître un peu bizarre à entendre).
Cette architecture laisse Meteor faire des choses sympathiques, parmi lesquelles la principale que Meteor appelle [database everywhere](http://docs.meteor.com/#sevenprinciples). Simplement, Meteor va prendre un sous-ensemble de votre base de données et le *copier sur le client*.
Cela implique deux idées importantes : premièrement, au lieu d'envoyer du code HTML au client, une application Meteor va envoyer **la donnée brute, véritablement**, et laisser le client se débrouiller avec ça ([data on the wire](http://docs.meteor.com/#sevenprinciples)). Deuxièmement, vous allez pouvoir **accéder aux données instantanément et même les modifier** sans avoir à attendre un autre aller-retour vers le serveur ([latency compensation](http://docs.meteor.com/#sevenprinciples)).
### Publier
Une base de données d'application peut contenir des dizaines de milliers de documents, lesquels peuvent être privés ou sensibles. Donc nous n'allons évidemment pas entièrement copier notre base de données sur le client, pour des raisons de sécurité et d'adaptabilité.
Par conséquent nous allons avoir besoin d'une méthode pour dire à Meteor quel **sous-ensemble** de données peut être envoyé au client, et nous l'effectuerons à l'aide d'une **publication**.
Revenons à Microscope. Nous avons ici tous les articles de l'application dans notre base de données :
<%= diagram "collections-1", "Tous les articles contenus dans la base de données.", "pull-center" %>
Bien que cette fonctionnalité n'est pas encore présente dans Microscope, nous allons imaginer que certains articles ont été signalés pour langage abusif. Bien que nous voulons les garder dans notre base de données, ils ne devront pas être rendus disponibles aux utilisateurs (i.e. envoyés au client).
Notre première tâche sera de dire à Meteor quelles données nous voulons *réellement* envoyer au client. Nous allons dire à Meteor que nous voulons seulement **publier** les articles non signalés :
<%= diagram "collections-2", "Exclure les articles signalés.", "pull-center" %>
Voici le code correspondant, qui résidera sur le serveur :
~~~js
// on the server
Meteor.publish('posts', function() {
return Posts.find({flagged: false});
});
~~~
Cela assure qu'il n'y a **aucun moyen possible** qu'un client soit capable d'accéder à un article signalé. C'est exactement comme ça que vous allez sécuriser une application Meteor : assurez-vous juste que vous publiez seulement les données que vous voulez fournir au client.
<% note do %>
### DDP
Fondamentalement, vous pouvez imaginer le système de publication/souscription comme un tunnel où transitent les données de la collection côté serveur (source) vers la collection côté client (cible).
Le protocole qui est parlé dans ce tunnel est appelé **DDP** (Distributed Data Protocol). Pour en savoir plus sur DDP, vous pouvez visionner [cette présentation de la Real-time Conference](http://2012.realtimeconf.com/video/matt-debergalis) par Matt DeBergalis (un des créateurs de Meteor), ou [cette capture vidéo](http://www.eventedmind.com/posts/meteor-subscriptions-and-ddp) par Chris Mather qui parcourt ce concept dans les moindres détails.
<% end %>
### Souscrire
Quand bien même nous voulons rendre les articles non signalés disponibles pour les clients, nous ne pouvons pas envoyer des milliers d'articles en une fois. Nous avons besoin d'un moyen de spécifier aux clients quel sous-ensemble de données ils ont besoin à un moment donné, et c'est exactement là que les **souscriptions** interviennent.
Les données auxquelles vous souscrivez seront **dupliquées** sur le client grâce à Minimongo, l'implémentation Meteor de MongoDB côté client.
Par exemple, disons que nous sommes en train de naviguer sur la page de profil de Bob, et nous voulons seulement afficher *ses* articles.
<%= diagram "collections-3", "Souscrire aux articles de Bob les copiera sur le client.", "pull-center" %>
Premièrement, nous modifierons notre publication pour prendre un paramètre :
~~~js
// on the server
Meteor.publish('posts', function(author) {
return Posts.find({flagged: false, author: author});
});
~~~
Et nous définirons ensuite ce paramètre au moment de la souscription à cette publication dans le code côté client de notre application :
~~~js
// on the client
Meteor.subscribe('posts', 'bob-smith');
~~~
C'est de cette façon qu'on rend une application Meteor adaptable côté client : au lieu de souscrire à *toutes* les données disponibles, on choisit les parties dont nous avons actuellement besoin. De cette façon, vous allez éviter les surcharges mémoire du navigateur quelle que soit la taille de la base de données côté serveur.
### Trouver
Maintenant qu'il est possible d'étiqueter les articles de Bob dans plusieurs catégories (par exemple "Javascript", "Ruby" et "Python"), on pourrait avoir envie de charger tous les articles en mémoire mais de n'afficher que ceux de la catégorie "Javascript". C'est dans ce cas de figure que "trouver" intervient.
<%= diagram "collections-4", "Sélectionner un sous-ensemble sur le client.", "pull-center" %>
Comme nous l'avons fait sur le serveur, nous utiliserons la fonction `Posts.find()` pour sélectionner un sous-ensemble de nos données.
~~~js
// on the client
Template.posts.helpers({
posts: function(){
return Posts.find({author: 'bob-smith', category: 'JavaScript'});
}
});
~~~
Maintenant que nous avons une bonne idée de quel rôle jouent les publications et les souscriptions, creusons un peu plus profond et observons quelques patrons d'implémentations.
### Autopublish
Si vous créez un projet Meteor à partir de rien (i.e. en utilisant `meteor create`), il aura automatiquement le paquet `autopublish` activé. Commençons par discuter de son rôle.
Le but de `autopublish` est de rendre très facile le début de développement de votre application Meteor, et ce en dupliquant automatiquement _toutes les données_ du serveur vers le client, ainsi en prenant soin des publications et des souscriptions pour vous.
<%= diagram "autopublish", "Autopublish", "pull-center"%>
Comment ça fonctionne ? Supposez que vous avez une collection appelée `'posts'` sur le serveur. Alors `autopublish` enverra automatiquement chaque article qu'il trouvera dans la collection posts Mongo vers une collection appelées `'posts'` sur le client (en considérant qu'il y en a un).
Donc si vous utilisez `autopublish`, vous n'avez pas besoin de penser aux publications. Les données sont omniprésentes, et les choses sont simples. Bien sûr, il y a des problèmes évidents d'avoir une copie complète de la base de données de l'application en cache sur chaque machine d'utilisateur.
Pour cette raison, autopublish est seulement approprié quand vous démarrez, et que vous n'avez pas encore réfléchi aux publications.
### Publier des collections complètes
Une fois que vous avez supprimé `autopublish`, vous allez rapidement vous rendre compte que toutes vos données ont disparues du client. Une façon simple de les faire revenir est simplement de copier ce que autopublish fait, et de publier une collection dans sa totalité. Par exemple :
~~~js
Meteor.publish('allPosts', function(){
return Posts.find();
});
~~~
<%= diagram "fullcollection", "Publier une collection complète", "pull-center" %>
Nous publions encore des collections complètes, mais au moins nous avons maintenant le contrôle sur quelles collections nous publions ou pas. Dans ce cas, nous publions la collection `Posts` mais pas `Comments`.
### Publier des collections partielles
Le niveau de contrôle suivant est de publier seulement une _partie_ d'une collection. Par exemple seuls les articles qui appartiennent à un certain auteur :
~~~js
Meteor.publish('somePosts', function(){
return Posts.find({'author':'Tom'});
});
~~~
<%= diagram "partialcollection", "Publier une collection partiellement", "pull-center" %>
<% note do %>
### En coulisses
Si vous avez lu la [documentation de publication Meteor](http://docs.meteor.com/#publishandsubscribe), vous avez peut-être été dépassé par l'utilisation de `added()` et `ready()` pour appliquer les attributs des enregistrements sur le client, et pour recoller ça avec les applications Meteor que vous avez déjà vues et qui n'utilisent pas ces méthodes.
La raison est que Meteor fournit une méthode vraiment très pratique : `_publishCursor()`. Vous n'avez jamais vu ça utilisé ? Peut-être pas directement, mais si vous retournez un [curseur](/chapter/meteor-vocabulary/)(i.e. `Posts.find({'author':'Tom'})`) dans une fonction de publication, c'est exactement ce qu'utilise Meteor.
Quand Meteor voit que la publication `somePosts` a retourné un curseur, il appelle `_publishCursor()` pour -- vous l'avez deviné -- publier ce curseur automatiquement.
Voici ce que `_publishCursor()` fait :
- Il vérifie le nom de la collection côté serveur.
- Il prend tous les documents correspondants du curseur et envoie celui-ci dans une collection côté client *du même nom*. (Il utilise `.added()` pour faire ça).
- A chaque moment qu'un document est ajouté, supprimé ou modifié, il envoie ces changements à la collection côté-client. (Il utilise `.observe()` sur le curseur et `.added()`, `.changed()` et `removed()` pour faire ça).
Dans l'exemple au-dessus, nous pouvons nous assurer que l'utilisateur a seulement les articles qui l'intéressent (ceux écrit par Tom) disponibles dans leur cache côté client.
<% end %>
### Publier des propriétés partielles
Nous avons vu comment publier seulement certains articles, mais nous pouvons continuer à affiner ! Voyons comment publier seulement certaines *propriétés* spécifiques.
Juste comme avant, nous allons utiliser `find()` pour retourner un curseur, mais cette fois nous allons exclure certains champs :
~~~js
Meteor.publish('allPosts', function(){
return Posts.find({}, {fields: {
date: false
}});
});
~~~
<%= diagram "partialproperties", "Publier des propriétés partiellement", "pull-center" %>
Bien sûr, nous pouvons également combiner deux techniques. Par exemple, si nous voulions retourner tous les articles de Tom en laissant de côté leurs dates, nous écririons :
~~~js
Meteor.publish('allPosts', function(){
return Posts.find({'author':'Tom'}, {fields: {
date: false
}});
});
~~~
### Résumé
Donc nous avons vu comment publier chaque propriété de tous les documents de chaque collection (avec `autopublish`) jusqu'à publier seulement _certaines_ propriétés de _certains_ documents de _certaines_ collections.
Ceci couvre les bases de ce que vous pouvez faire avec les publications Meteor, et ces simples techniques s'occuperont de la vaste majorité des cas d'utilisation.
Parfois, vous aurez besoin d'aller plus loin en combinant, reliant, assemblant des publications. Nous allons en discuter dans un prochain chapitre !