Buscar..
Observaciones
Dentro del subsistema de datos de Meteor, una publicación de servidor y sus correspondientes suscripciones de clientes son los principales mecanismos de transporte de datos reactivos y en vivo donde los datos subyacentes se sincronizan constantemente entre el servidor y el cliente.
Suscripción básica y publicación
Primero, elimine autopublish
. autopublish
publica automáticamente la base de datos completa en el lado del cliente, por lo que no se pueden ver los efectos de las publicaciones y suscripciones.
Para eliminar autopublish
:
$ meteor remove autopublish
Entonces puedes crear publicaciones. A continuación se muestra un ejemplo completo.
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');
})
}
Publicaciones globales
Una publicación global no posee un nombre y no requiere una suscripción del cliente conectado y, por lo tanto, está disponible para el cliente conectado tan pronto como el cliente se conecta al servidor.
Para lograr esto, uno simplemente nombra la publicación como null
como tal
Meteor.publish(null, function() {
return SomeCollection.find();
})
Publicaciones nombradas
Una publicación nombrada es aquella que posee un nombre y debe suscribirse explícitamente desde el cliente.
Considere este código del lado del servidor:
Meteor.publish('somePublication', function() {
return SomeCollection.find()
})
El cliente debe solicitarlo por:
Meteor.subscribe('somePublication')
Plantilla de suscripciones a ámbito
El sistema de plantillas predeterminado de Meteor, las barras de espacio y su subsistema de representación subyacente Blaze se integran aparentemente con los métodos de ciclo de vida de la publicación, de modo que una simple pieza de código de plantilla puede suscribirse a sus propios datos, detener y limpiar sus propios rastros durante el desmontaje de la plantilla.
Para aprovechar esto, es necesario suscribirse a la instancia de la plantilla, en lugar del símbolo Meteor
así:
Primero configura la plantilla
<template name="myTemplate">
We will use some data from a publication here
</template>
Luego toque en la correspondiente devolución de llamada del ciclo de vida
Template.myTemplate.onCreated(function() {
const templateInstance = this;
templateInstance.subscribe('somePublication')
})
Ahora, cuando esta plantilla se destruye, la publicación también se detendrá automáticamente.
Nota: los datos a los que está suscrito estarán disponibles para todas las plantillas.
Publique en una colección de cliente efímera llamada.
Porque si tienes que afinar lo publicado.
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));
});
}
Creación y respuesta a un error en una publicación.
En el servidor, puede crear una publicación como esta. this.userId
es el ID del usuario que ha iniciado sesión actualmente. Si ningún usuario ha iniciado sesión, es posible que desee lanzar un error y responder a él.
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();
}
});
En el cliente, puede responder con lo siguiente.
Meteor.subscribe('protected_data', {
onError(err) {
if (err.error === 403) {
alert("Looks like you're not logged in");
}
},
});
Archivo / importaciones / colecciones / Secretos crea una referencia a la colección de secretos de la siguiente manera:
const Secrets = new Mongo.Collection('secrets');
Reactivamente re-suscribirse a una publicación
Se puede usar una plantilla de ejecución automática para (re) suscribirse a una publicación. Establece un contexto reactivo que se vuelve a ejecutar cada vez que los datos reactivos dependen de los cambios . Además, una ejecución automática siempre se ejecuta una vez (la primera vez que se ejecuta).
Las ejecuciones automáticas de plantillas normalmente se ponen en un método onCreated
.
Template.myTemplate.onCreated(function() {
this.parameter = new ReactiveVar();
this.autorun(() => {
this.subscribe('myPublication', this.parameter.get());
});
});
Esto se ejecutará una vez (la primera vez) y establecerá una suscripción. Luego se volverá a ejecutar cada vez que cambie la variable reactiva del parameter
.
Espere en la vista Blaze mientras se están recuperando los datos publicados
Código de plantilla JS
Template.templateName.onCreated(function(){
this.subscribe('subsription1');
this.subscribe('subscription2');
});
Código HTML de la plantilla
<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>
Validación de cuenta de usuario en publicación
A veces es una buena idea asegurar aún más sus publicaciones al requerir un inicio de sesión de usuario. Aquí es cómo lograr esto a través de 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 [];
}
});
Publicar multiples cursores
Se pueden publicar varios cursores de base de datos desde el mismo método de publicación devolviendo una serie de cursores.
Los cursores "hijos" se tratarán como uniones y no serán reactivos.
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];
});
Simular retraso en publicaciones.
En el mundo real, podrían producirse retrasos en la conexión y el servidor, para simular retrasos en el entorno de desarrollo Meteor._sleepForMs(ms);
puede ser usado
Meteor.publish('USER_DATA', function() {
Meteor._sleepForMs(3000); // Simulate 3 seconds delay
return Meteor.users.find({});
});
Fusionando Publicaciones
Las publicaciones se pueden combinar en el cliente, lo que da como resultado documentos con formas diferentes dentro de un solo cursor. El siguiente ejemplo representa cómo un directorio de usuarios puede publicar una cantidad mínima de datos públicos para los usuarios de una aplicación y proporciona un perfil más detallado para el usuario que ha iniciado sesión.
// 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
}});
});