Recherche…
Remarques
Dans le sous-système de données de Meteor, une publication de serveur et ses abonnements client correspondants sont les principaux mécanismes de transport de données réactif et en direct, où les données sous-jacentes sont constamment synchronisées entre le serveur et le client.
Abonnement de base et publication
Tout d'abord, supprimez la autopublish
. autopublish
publication automatique publie automatiquement la base de données entière sur le côté client, de sorte que les effets des publications et des abonnements ne sont pas visibles.
Pour supprimer la autopublish
:
$ meteor remove autopublish
Ensuite, vous pouvez créer des publications. Voici un exemple complet.
import { Mongo } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';
const Todos = new Mongo.Collection('todos');
const TODOS = [
{ title: 'Create documentation' },
{ title: 'Submit to Stack Overflow' }
];
if (Meteor.isServer) {
Meteor.startup(function () {
TODOS.forEach(todo => {
Todos.upsert(
{ title: todo.title },
{ $setOnInsert: todo }
);
});
});
// first parameter is a name.
Meteor.publish('todos', function () {
return Todos.find();
});
}
if (Meteor.isClient) {
// subscribe by name to the publication.
Meteor.startup(function () {
Meteor.subscribe('todos');
})
}
Publications mondiales
Une publication globale ne possède pas de nom et ne nécessite pas d'abonnement du client connecté et est donc disponible pour le client connecté dès que le client se connecte au serveur.
Pour ce faire, on nomme simplement la publication comme null
comme ça
Meteor.publish(null, function() {
return SomeCollection.find();
})
Publications nommées
Une publication nommée est une publication qui possède un nom et doit être explicitement abonnée au client.
Considérez ce code côté serveur:
Meteor.publish('somePublication', function() {
return SomeCollection.find()
})
Le client doit le demander par:
Meteor.subscribe('somePublication')
Abonnements à des modèles
Le système de template par défaut de Meteor Spacebars et son sous-système de rendu sous-jacent Blaze s'intègrent parfaitement aux méthodes du cycle de vie de la publication.
Pour tirer parti de cela, il faut s'inscrire sur l'instance du modèle, plutôt que sur le symbole Meteor
comme suit:
Commencez par configurer le modèle
<template name="myTemplate">
We will use some data from a publication here
</template>
Puis appuyez sur le rappel de cycle de vie correspondant
Template.myTemplate.onCreated(function() {
const templateInstance = this;
templateInstance.subscribe('somePublication')
})
Maintenant, lorsque ce modèle est détruit, la publication sera également automatiquement arrêtée.
Remarque: Les données auxquelles vous êtes abonné seront disponibles pour tous les modèles.
Publier dans une collection nommée éphémère côté client.
Car si vous devez affiner ce qui est publié.
import { Mongo } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';
import { Random } from 'meteor/random';
if (Meteor.isClient) {
// established this collection on the client only.
// a name is required (first parameter) and this is not persisted on the server.
const Messages = new Mongo.Collection('messages');
Meteor.startup(function () {
Meteor.subscribe('messages');
Messages.find().observe({
added: function (message) {
console.log('Received a new message at ' + message.timestamp);
}
});
})
}
if (Meteor.isServer) {
// this will add a new message every 5 seconds.
Meteor.publish('messages', function () {
const interval = Meteor.setInterval(() => {
this.added('messages', Random.id(), {
message: '5 seconds have passed',
timestamp: new Date()
})
}, 5000);
this.added('messages', Random.id(), {
message: 'First message',
timestamp: new Date()
});
this.onStop(() => Meteor.clearInterval(interval));
});
}
Créer et répondre à une erreur sur une publication.
Sur le serveur, vous pouvez créer une publication comme celle-ci. this.userId
est l'ID de l'utilisateur actuellement connecté. Si aucun utilisateur n'est connecté, vous pouvez générer une erreur et y répondre.
import Secrets from '/imports/collections/Secrets';
Meteor.publish('protected_data', function () {
if (!this.userId) {
this.error(new Meteor.Error(403, "Not Logged In."));
this.ready();
} else {
return Secrets.find();
}
});
Sur le client, vous pouvez répondre avec les éléments suivants.
Meteor.subscribe('protected_data', {
onError(err) {
if (err.error === 403) {
alert("Looks like you're not logged in");
}
},
});
Fichier / imports / collections / Secrets crée une référence à la collection de secrets comme ci-dessous:
const Secrets = new Mongo.Collection('secrets');
Réinscription réactive à une publication
Un modèle autorun peut être utilisé pour (ré) souscrire à une publication. Il établit un contexte réactif qui est ré-exécuté chaque fois que des données réactives dépendent de changements . De plus, une exécution automatique s'exécute toujours une fois (la première fois qu'elle est exécutée).
Les autoruns de modèle sont normalement placés dans une méthode onCreated
.
Template.myTemplate.onCreated(function() {
this.parameter = new ReactiveVar();
this.autorun(() => {
this.subscribe('myPublication', this.parameter.get());
});
});
Cela fonctionnera une fois (la première fois) et mettre en place un abonnement. Il sera alors ré-exécuté chaque fois que la variable réactive du parameter
change.
Attendez dans la vue Blaze pendant l'extraction des données publiées
Code JS du modèle
Template.templateName.onCreated(function(){
this.subscribe('subsription1');
this.subscribe('subscription2');
});
Code HTML du modèle
<template name="templateName">
{{#if Template.subscriptionsReady }}
//your actual view with data. it can be plain HTML or another template
{{else}}
//you can use any loader or a simple header
<h2> Please wait ... </h2>
{{/if}}
</template>
Validation du compte d'utilisateur sur Publier
Il est parfois utile de sécuriser davantage vos publications en exigeant une connexion utilisateur. Voici comment vous y parvenez via Meteor.
import { Recipes } from '../imports/api/recipes.js';
import { Meteor } from 'meteor/meteor';
Meteor.publish('recipes', function() {
if(this.userId) {
return Recipe.find({});
} else {
this.ready(); // or: return [];
}
});
Publier plusieurs curseurs
Plusieurs curseurs de base de données peuvent être publiés à partir de la même méthode de publication en renvoyant un tableau de curseurs.
Les curseurs "enfants" seront traités comme des jointures et ne seront pas réactifs.
Meteor.publish('USER_THREAD', function(postId) {
let userId = this.userId;
let comments = Comments.find({ userId, postId });
let replies = Replies.find({ userId, postId });
return [comments, replies];
});
Simuler le retard dans les publications
Dans le monde réel, des délais de connexion et de serveur pourraient survenir, pour simuler des retards dans l'environnement de développement Meteor._sleepForMs(ms);
peut être utilisé
Meteor.publish('USER_DATA', function() {
Meteor._sleepForMs(3000); // Simulate 3 seconds delay
return Meteor.users.find({});
});
Fusion de publications
Les publications peuvent être fusionnées sur le client, ce qui permet de créer des documents de forme différente dans un même curseur. L'exemple suivant montre comment un annuaire d'utilisateurs peut publier une quantité minimale de données publiques pour les utilisateurs d'une application et fournir un profil plus détaillé pour l'utilisateur connecté.
// client/subscriptions.js
Meteor.subscribe('usersDirectory');
Meteor.subscribe('userProfile', Meteor.userId());
// server/publications.js
// Publish users directory and user profile
Meteor.publish("usersDirectory", function (userId) {
return Meteor.users.find({}, {fields: {
'_id': true,
'username': true,
'emails': true,
'emails[0].address': true,
// available to everybody
'profile': true,
'profile.name': true,
'profile.avatar': true,
'profile.role': true
}});
});
Meteor.publish('userProfile', function (userId) {
return Meteor.users.find({_id: this.userId}, {fields: {
'_id': true,
'username': true,
'emails': true,
'emails[0].address': true,
'profile': true,
'profile.name': true,
'profile.avatar': true,
'profile.role': true,
// privately accessible items, only availble to the user logged in
'profile.visibility': true,
'profile.socialsecurity': true,
'profile.age': true,
'profile.dateofbirth': true,
'profile.zip': true,
'profile.workphone': true,
'profile.homephone': true,
'profile.mobilephone': true,
'profile.applicantType': true
}});
});