javascript - new - meteor tutorial español
Comprender Meteor Publish/Subscribe (4)
La regla básica aquí es publish
y subscribed
nombres de variables subscribed
deben ser los mismos en el lado del cliente y del servidor.
Los nombres de las colecciones en Mongo DB y el lado del cliente deben ser iguales.
Supongamos que estoy usando publicar y suscribirme para mi colección llamada employees
entonces el código se vería como
lado del servidor
Aquí el uso de la palabra clave var
es opcional (use esta palabra clave para hacer que la colección sea local para este archivo).
CollectionNameOnServerSide = new Mongo.Collection(''employees'');
Meteor.publish(''employeesPubSub'', function() {
return CollectionNameOnServerSide.find({});
});
archivo .js del lado del cliente
CollectionNameOnClientSide = new Mongo.Collection(''employees'');
var employeesData = Meteor.subscribe(''employeesPubSub'');
Template.templateName.helpers({
''subcribedDataNotAvailable'' : function(){
return !employeesData.ready();
},
''employeeNumbers'' : () =>{
CollectionNameOnClientSide.find({''empId'':1});
}
});
lado del cliente .html archivo
Aquí podemos usar el método de ayuda subcribedDataNotAvailable
para saber si los datos están listos en el lado del cliente, si los datos están listos, entonces imprima los números de employeeNumbers
utilizando el método employeeNumbers
helper.
<TEMPLATE name="templateName">
{{#if subcribedDataNotAvailable}}
<h1> data loading ... </h1>
{{else}}
{{#each employeeNumbers }}
{{this}}
{{/each}}
{{/if}}
<TEMPLATE>
Tengo una configuración de aplicación simple que muestra una lista de Projects
. He eliminado el paquete autopublish
para no enviar todo al cliente.
<template name="projectsIndex">
{{#each projects}}
{{name}}
{{/each}}
</template>
Cuando se activó autopublish
, esto mostraría todos los proyectos:
if Meteor.isClient
Template.projectsIndex.projects = Projects.find()
Con esto eliminado, tengo que hacer adicionalmente:
if Meteor.isServer
Meteor.publish "projects", ->
Projects.find()
if Meteor.isClient
Meteor.subscribe "projects"
Template.projectsIndex.projects = Projects.find()
Entonces, ¿es correcto decir que el método find()
lado del cliente solo busca registros que han sido publicados desde el lado del servidor? Me ha estado molestando porque sentí que solo debería estar llamando a find()
una vez.
Las colecciones, publicaciones y suscripciones son un área engañosa de Meteor, que la documentación podría analizar con más detalle, a fin de evitar la confusion frequent , que a veces se amplifica por una terminología confusa .
Aquí está Sacha Greif (coautor de DiscoverMeteor ) que explica publicaciones y suscripciones en una diapositiva:
Para comprender correctamente por qué necesita llamar a find()
más de una vez, necesita comprender cómo funcionan las colecciones, publicaciones y suscripciones en Meteor:
Usted define colecciones en MongoDB. Sin Meteor involucrado todavía. Estas colecciones contienen registros de bases de datos (también llamados "documentos" por Mongo y Meteor , pero un "documento" es más general que un registro de base de datos, por ejemplo, una especificación de actualización o un selector de consulta también son documentos - objetos JavaScript que contienen
field: value
pares).Luego defines collections en el servidor Meteor con
MyCollection = new Mongo.Collection(''collection-name-in-mongo'')
Estas colecciones contienen todos los datos de las colecciones MongoDB, y puede ejecutar
MyCollection.find({...})
en ellas, lo que devolverá un cursor (un conjunto de registros, con métodos para iterar a través de ellos y devolverlos).Este cursor (la mayoría de las veces) se usa para publish (enviar) un conjunto de registros (llamado "conjunto de registros" ). Opcionalmente, puede publicar solo some campos de esos registros. Son conjuntos de registros ( no colecciones) a los que los clientes se subscribe . La publicación se realiza mediante una función de publicación , que se invoca cada vez que un nuevo cliente se suscribe, y que puede tomar parámetros para administrar qué registros devolver (por ejemplo, una identificación de usuario, para devolver solo los documentos de ese usuario).
En el cliente , tiene colecciones de Minimongo que reflejan parcialmente algunos de los registros del servidor. "Parcialmente" porque pueden contener solo algunos de los campos, y "algunos de los registros" porque generalmente desea enviar al cliente solo los registros que necesita, para acelerar la carga de la página, y solo aquellos que necesita y tiene permiso para acceso.
Minimongo es esencialmente una implementación en memoria y no persistente de Mongo en JavaScript puro. Sirve como un caché local que almacena solo el subconjunto de la base de datos con la que está trabajando este cliente. Las consultas en el cliente (buscar) se sirven directamente desde este caché, sin hablar con el servidor.
Estas colecciones de Minimongo están inicialmente vacías. Ellos están llenos por
Meteor.subscribe(''record-set-name'')
llamadas. Tenga en cuenta que el parámetro para subscribe no es un nombre de colección; es el nombre de un conjunto de registros que el servidor utilizó en la llamada de
publish
. La llamadasubscribe()
suscribe al cliente a un conjunto de registros : un subconjunto de registros de la colección de servidores (por ejemplo, las 100 publicaciones más recientes), con todo o un subconjunto de los campos en cada registro (por ejemplo, solotitle
ydate
). ¿Cómo sabe Minimongo en qué colección colocar los registros entrantes? El nombre de la colección será el argumento decollection
utilizado en las devoluciones de llamadaadded
,changed
yremoved
del controlador de publicación, o si faltan (lo cual es el caso la mayoría de las veces), será el nombre de la colección MongoDB en el servidor.
Modificar registros
Aquí es donde Meteor hace las cosas muy convenientes: cuando modificas un registro (documento) en la colección de Minimongo en el cliente, Meteor actualiza instantáneamente todas las plantillas que dependen de él, y también envía los cambios de vuelta al servidor, que a su vez almacenará los cambios en MongoDB y los enviará a los clientes apropiados que se hayan suscrito a un conjunto de registros que incluya ese documento. Esto se llama compensación de latencia y es uno de los siete principios básicos de Meteor .
Suscripciones múltiples
Puede tener un montón de suscripciones que extraen diferentes registros, pero todas terminarán en la misma colección en el cliente si provienen de la misma colección en el servidor, según su _id
. Esto no se explica con claridad, pero está implícito en los documentos de Meteor:
Cuando se suscribe a un conjunto de registros, le dice al servidor que envíe registros al cliente. El cliente almacena estos registros en las colecciones locales de Minimongo, con el mismo nombre que el argumento de
collection
utilizado en las devoluciones de llamadaadded
,changed
yremoved
del manejador de publicaciones. Meteor pondrá en cola los atributos entrantes hasta que declare Mongo.Collection en el cliente con el nombre de la colección correspondiente.
Lo que no se explica es lo que ocurre cuando no se usan explícitamente los controladores added
, changed
, removed
o publicados, lo que ocurre la mayoría de las veces. En este caso más común, el argumento de recolección es (como era de esperar) tomado del nombre de la colección MongoDB que declaró en el servidor en el paso 1. Pero lo que esto significa es que puede tener diferentes publicaciones y suscripciones con diferentes nombres, y todo el los registros terminarán en la misma colección en el cliente. Hasta el nivel de los campos de nivel superior , Meteor se encarga de realizar una unión establecida entre los documentos, de modo que las suscripciones se puedan superponer: publique funciones que envíen diferentes campos de nivel superior al trabajo del cliente, uno al lado del otro y en el cliente, el documento en el la colección será la unión de los dos conjuntos de campos .
Ejemplo: suscripciones múltiples que llenan la misma colección en el cliente
Tiene una colección BlogPosts, que declara de la misma manera tanto en el servidor como en el cliente, aunque hace cosas diferentes:
BlogPosts = new Mongo.Collection(''posts'');
En el cliente, BlogPosts
puede obtener registros de:
una suscripción a las 10 publicaciones de blog más recientes
// server Meteor.publish(''posts-recent'', function publishFunction() { return BlogPosts.find({}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe(''posts-recent'');
una suscripción a las publicaciones del usuario actual
// server Meteor.publish(''posts-current-user'', function publishFunction() { return BlogPosts.find({author: this.userId}, {sort: {date: -1}, limit: 10}); // this.userId is provided by Meteor - http://docs.meteor.com/#publish_userId } Meteor.publish(''posts-by-user'', function publishFunction(who) { return BlogPosts.find({authorId: who._id}, {sort: {date: -1}, limit: 10}); } // client Meteor.subscribe(''posts-current-user''); Meteor.subscribe(''posts-by-user'', someUser);
una suscripción a las publicaciones más populares
- etc.
Todos estos documentos provienen de la colección de posts
en MongoDB, a través de la colección BlogPosts
en el servidor, y terminan en la colección BlogPosts
en el cliente.
Ahora podemos entender por qué necesita llamar a find()
más de una vez, la segunda vez que está en el cliente, porque los documentos de todas las suscripciones terminarán en la misma colección, y debe buscar solo a aquellos que le interesan. Por ejemplo, para obtener las publicaciones más recientes en el cliente, simplemente duplica la consulta del servidor:
var recentPosts = BlogPosts.find({}, {sort: {date: -1}, limit: 10});
Esto devolverá un cursor a todos los documentos / registros que el cliente ha recibido hasta el momento, tanto las publicaciones principales como las publicaciones del usuario. ( gracias Geoffrey ).
Sí, el cliente find () solo devuelve documentos que están en el cliente en Minimongo. De docs :
En el cliente, se crea una instancia de Minimongo. Minimongo es esencialmente una implementación en memoria y no persistente de Mongo en JavaScript puro. Sirve como un caché local que almacena solo el subconjunto de la base de datos con la que está trabajando este cliente. Las consultas en el cliente (buscar) se sirven directamente desde este caché, sin hablar con el servidor.
Como dices, publish () especifica qué documentos tendrá el cliente.
// on the server
Meteor.publish(''posts'', function() {
return Posts.find();
});
// on the client
Meteor.subscribe(''posts'');