Szukaj…
Uwagi
W podsystemie danych Meteor publikacja serwera i odpowiadające mu subskrypcje klientów są głównymi mechanizmami reaktywnego przesyłania danych na żywo, w których dane podstawowe są stale synchronizowane między serwerem a klientem.
Podstawowa subskrypcja i publikacja
Najpierw usuń automatyczne autopublish
. autopublish
automatycznie publikuje całą bazę danych po stronie klienta, więc efekty publikacji i subskrypcji nie są widoczne.
Aby usunąć automatyczne autopublish
:
$ meteor remove autopublish
Następnie możesz tworzyć publikacje. Poniżej znajduje się pełny przykład.
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');
})
}
Publikacje globalne
Publikacja globalna nie ma nazwy i nie wymaga subskrypcji od podłączonego klienta, dlatego jest dostępna dla podłączonego klienta, gdy tylko klient połączy się z serwerem.
Aby to osiągnąć, wystarczy po prostu nazwać publikację taką jak null
Meteor.publish(null, function() {
return SomeCollection.find();
})
Nazwane publikacje
Publikacja nazwana to taka, która ma nazwę i musi zostać wyraźnie zasubskrybowana przez klienta.
Rozważ ten kod po stronie serwera:
Meteor.publish('somePublication', function() {
return SomeCollection.find()
})
Klient musi o to poprosić:
Meteor.subscribe('somePublication')
Subskrypcje o zasięgu szablonowym
Domyślny system szablonów Meteor Paski kosmiczne i leżący u jego podstaw podsystem renderowania Blaze bez trudu integrują się z metodami cyklu życia publikacji, dzięki czemu prosty fragment kodu szablonu może subskrybować własne dane, zatrzymać i wyczyścić własne ślady podczas usuwania szablonu.
Aby się do tego przyłączyć, należy zasubskrybować instancję szablonu, a nie symbol Meteor
:
Najpierw skonfiguruj szablon
<template name="myTemplate">
We will use some data from a publication here
</template>
Następnie dotknij odpowiedniego wywołania zwrotnego cyklu życia
Template.myTemplate.onCreated(function() {
const templateInstance = this;
templateInstance.subscribe('somePublication')
})
Teraz, gdy ten szablon zostanie zniszczony, publikacja również zostanie automatycznie zatrzymana.
Uwaga: subskrybowane dane będą dostępne dla wszystkich szablonów.
Opublikuj w efemerycznej kolekcji o nazwie po stronie klienta.
Bo jeśli musisz dostosować to, co jest publikowane.
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));
});
}
Tworzenie i reagowanie na błąd w publikacji.
Na serwerze możesz utworzyć taką publikację. this.userId
to identyfikator użytkownika, który jest aktualnie zalogowany. Jeśli żaden użytkownik nie jest zalogowany, możesz chcieć this.userId
błąd i odpowiedzieć na niego.
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();
}
});
Na kliencie możesz odpowiedzieć na następujące pytania.
Meteor.subscribe('protected_data', {
onError(err) {
if (err.error === 403) {
alert("Looks like you're not logged in");
}
},
});
Plik / import / kolekcje / Sekrety tworzy odniesienie do kolekcji sekretów, jak poniżej:
const Secrets = new Mongo.Collection('secrets');
Reaktywne subskrybowanie publikacji
Szablon autorun może być użyty do (ponownego) subskrybowania publikacji. Ustanawia reaktywny kontekst, który jest ponownie uruchamiany za każdym razem, gdy jakiekolwiek reaktywne dane zależą od zmian . Ponadto autorun zawsze uruchamia się raz (przy pierwszym uruchomieniu).
Autoruny szablonów są zwykle umieszczane w metodzie onCreated
.
Template.myTemplate.onCreated(function() {
this.parameter = new ReactiveVar();
this.autorun(() => {
this.subscribe('myPublication', this.parameter.get());
});
});
Uruchomi się to raz (po raz pierwszy) i skonfiguruje subskrypcję. Następnie będzie uruchamiany ponownie, gdy zmieni się zmienna reaktywna parameter
.
Poczekaj w widoku Blaze na pobieranie danych opublikowanych
Kod JS szablonu
Template.templateName.onCreated(function(){
this.subscribe('subsription1');
this.subscribe('subscription2');
});
Kod HTML szablonu
<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>
Sprawdzanie poprawności konta użytkownika podczas publikowania
Czasami warto zabezpieczyć swoje publikacje, wymagając loginu użytkownika. Oto jak to osiągnąć przez 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 [];
}
});
Opublikuj wiele kursorów
Wiele kursorów bazy danych można opublikować z tej samej metody publikacji, zwracając tablicę kursorów.
Kursory „potomne” będą traktowane jak złączenia i nie będą reagować.
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];
});
Symuluj opóźnienie w publikacjach
W prawdziwym świecie mogą wystąpić opóźnienia połączenia i serwera, aby zasymulować opóźnienia w środowisku programistycznym Meteor._sleepForMs(ms);
może być użyty
Meteor.publish('USER_DATA', function() {
Meteor._sleepForMs(3000); // Simulate 3 seconds delay
return Meteor.users.find({});
});
Scalanie publikacji
Publikacje mogą być scalane na kliencie, w wyniku czego dokumenty o różnych kształtach znajdują się w obrębie jednego kursora. Poniższy przykład przedstawia, w jaki sposób katalog użytkownika może publikować minimalną ilość danych publicznych dla użytkowników aplikacji i zapewnia bardziej szczegółowy profil dla zalogowanego użytkownika.
// 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
}});
});