Поиск…
замечания
В подсистеме данных Meteor публикация сервера и соответствующие подписки клиента являются основными механизмами реактивной передачи данных в реальном времени, когда базовые данные постоянно синхронизируются между сервером и клиентом.
Основная подписка и публикация
Сначала удалите autopublish
. autopublish
автоматически публикует всю базу данных на стороне клиента, поэтому эффекты публикаций и подписки не могут быть видны.
Чтобы удалить autopublish
:
$ meteor remove autopublish
Затем вы можете создавать публикации. Ниже приведен полный пример.
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');
})
}
Глобальные публикации
Глобальная публикация не имеет имени и не требует подписки от подключенного клиента, и поэтому она доступна подключенному клиенту, как только клиент подключается к серверу.
Чтобы добиться этого, можно просто назвать публикацию null
Meteor.publish(null, function() {
return SomeCollection.find();
})
Названные публикации
Именованная публикация - это имя, которое имеет имя и должно быть явно подписано клиентом.
Рассмотрим этот код на стороне сервера:
Meteor.publish('somePublication', function() {
return SomeCollection.find()
})
Клиент должен запросить его:
Meteor.subscribe('somePublication')
Подписчики с подменю шаблонов
Система моделирования шаблонов Meteor Spacebars и ее базовая подсистема рендеринга Blaze без видимости интегрируются с методами жизненного цикла публикации, так что простая часть кода шаблона может подписываться на свои собственные данные, останавливать и очищать свои собственные трассы во время разрыва шаблона.
Чтобы воспользоваться этим, нужно подписаться на экземпляр шаблона, а не на символ Meteor
:
Сначала настройте шаблон
<template name="myTemplate">
We will use some data from a publication here
</template>
Затем коснитесь соответствующего обратного вызова жизненного цикла
Template.myTemplate.onCreated(function() {
const templateInstance = this;
templateInstance.subscribe('somePublication')
})
Теперь, когда этот шаблон будет уничтожен, публикация также будет остановлена автоматически.
Примечание. Данные, на которые подписаны, будут доступны для всех шаблонов.
Публикация в эфемерной клиентской стороне.
Ибо, если вам нужно настроить то, что опубликовано.
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));
});
}
Создание и реагирование на ошибку в публикации.
На сервере вы можете создать такую публикацию. this.userId
- это идентификатор пользователя, который в настоящий момент вошел в систему. Если ни один пользователь не вошел в систему, вам может потребоваться выбросить ошибку и ответить на нее.
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();
}
});
На клиенте вы можете ответить следующим.
Meteor.subscribe('protected_data', {
onError(err) {
if (err.error === 403) {
alert("Looks like you're not logged in");
}
},
});
Файл / импорт / коллекции / Секреты создают ссылку на коллекцию секретов, как показано ниже:
const Secrets = new Mongo.Collection('secrets');
Реактивировать повторную подписку на публикацию
Автозапуск шаблонов может использоваться для (пере) подписки на публикацию. Он устанавливает реактивный контекст, который повторно выполняется, когда любые реактивные данные зависят от изменений . Кроме того, автозапуск всегда выполняется один раз (при первом запуске).
onCreated
шаблонов обычно помещается в метод onCreated
.
Template.myTemplate.onCreated(function() {
this.parameter = new ReactiveVar();
this.autorun(() => {
this.subscribe('myPublication', this.parameter.get());
});
});
Это будет запускаться один раз (первый раз) и настроить подписку. Затем он будет повторно запускаться всякий раз, когда изменяется переменная parameter
.
Подождите в режиме Blaze, пока публикуются данные
Шаблон JS-кода
Template.templateName.onCreated(function(){
this.subscribe('subsription1');
this.subscribe('subscription2');
});
Шаблон HTML-кода
<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>
Проверка учетной записи пользователя при публикации
Иногда это хорошая идея для дальнейшей защиты ваших изданий, требуя входа пользователя в систему. Вот как вы достигаете этого через Метеор.
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 [];
}
});
Публикация нескольких курсоров
Несколько курсоров базы данных могут быть опубликованы из одного метода публикации, возвращая массив курсоров.
Курсоры «дети» будут рассматриваться как объединения и не будут реагировать.
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];
});
Моделировать задержку публикаций
В реальном мире могут возникнуть задержки соединения и сервера, чтобы имитировать задержки в среде разработки Meteor._sleepForMs(ms);
может быть использован
Meteor.publish('USER_DATA', function() {
Meteor._sleepForMs(3000); // Simulate 3 seconds delay
return Meteor.users.find({});
});
Объединение публикаций
Публикации могут быть объединены на клиенте, в результате чего документы с разными формами формируются в пределах одного курсора. В следующем примере показано, как каталог пользователя может публиковать минимальное количество общедоступных данных для пользователей приложения и предоставлять более подробный профиль для зарегистрированного пользователя.
// 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
}});
});