forked from DiscoverMeteor/DiscoverMeteor_fr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
04s-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'étaient pas encore là. Disons que vous développez une simple applications rails. Quand un utilisateur atteint votre site, le client (i.e. votre navigateur) envoit 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 prends 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 coté client qui va s'executer **sur le client** (le navigateur).
<%= diagram "client-serveur", "Envoyer un sous-ensemble de la base de données au client.", "pull-right" %>
C'est comme un marchand qui ne trouve pas seulement le livre pour vous, mais qui vous suit jusque chez vous pour vous lire le livre au moment de dormir (ce que 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 la *copier sur le client*.
Cela implique deux grosses idées : premièrement, au lieu d'envoyer du code HTML au client, une application Meteor va envoyer **la donnée brute, actuelle** 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** 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é ou sensible. Donc nous n'allons évidemment pas juste copier notre entière 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 rendu disponible aux utilisateurs (i.e. envoyé 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 coté-serveur (source) vers la collection coté-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 (one of the founders of Meteor), ou [ce screencast](http://www.eventedmind.com/posts/meteor-subscriptions-and-ddp) par Chris Mather qui parcourt ce concept dans le moindre détail.
<% end %>
### Souscrire
Quand bien même nous voulons rendre les articles non signalés disponibles pour les clients, nous ne pouvons pas juste 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 auquelles vous souscrivez sera **dupliqué** sur le client grace à Minimongo, l'implémentation Meteor de MongoDB coté-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 modifierions 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 coté-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 coté-client : au lieu de souscrire à *toutes* les données disponibles, on choisit les parties que nous avons actuellement besoin. De cette façon, vous allez éviter les surcharge mémoire du navigateur quelle que soit la taille de la base de données coté-serveur.
### Trouver
Maintenant que les articles de Bob arrivent à être étiqueté dans plusieurs catégories (par exemple : "Javascript", "Ruby, et "Python"). Peut-être que nous voulons toujours charger tous les articles de Bob en mémoire, mais nous voulons seulement afficher ceux de la catégorie "Javascript". C'est ici que "trouver" intervient.
<%= diagram "collections-4", "Sélectionner un sous-ensemble sur le client.", "pull-center" %>
Juste 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 joue 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é. Comme point de départ, discutons de ce que ça fait exactement.
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ées `'posts'` sur le serveur. Alors `autopublish` enverra automatiquement chaque article qu'il trouvera dans la collection posts Mongo vers une collections 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 sur les publications.
### Publier des collections complètes
Une fois que vous avez supprimé `autopublish`, vous allez rapidement réaliser que toutes vos données ont disparues du client. Une façon simple de revenir et 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à vu et qui n'utilise pas ces méthodes.
La raison est que Meteor fournit une méthodes 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 coté-serveur.
- Il prend tous les documents correspondants du curseur et envoie celui-ci dans une collection coté-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 sommes pouvons nous assurer que l'utilisateur a seulement les articles qui l'interessent (ceux écrit par Tom) disponible dans leur cache côté client.
<% end %>
### Publier des propriétés partielles
Nous avons vu comment publiquer seulement certains articles, mais vous 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!