サーチ…
備考
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
として単に指定し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
は現在ログインしているユーザーのIDです。ユーザーがログインしていない場合は、エラーをスローして応答することができます。
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');
出版物に積極的に再購読する
テンプレートの自動実行を使用して、出版物に(再)購読することができます。これは、反応性のあるデータを変更するたびに再実行される反応的なコンテキストを確立します 。さらに、自動実行は常に1回実行されます(最初に実行されたとき)。
テンプレート自動実行は、通常、 onCreated
メソッドに置かれonCreated
。
Template.myTemplate.onCreated(function() {
this.parameter = new ReactiveVar();
this.autorun(() => {
this.subscribe('myPublication', this.parameter.get());
});
});
これは1回(初回)実行され、サブスクリプションを設定します。 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({});
});
出版物のマージ
パブリケーションをクライアント上でマージすると、1つのカーソル内に異なる形のドキュメントが作成されます。次の例は、ユーザーディレクトリがアプリユーザーのパブリックデータを最小限に公開し、ログインしたユーザーの詳細なプロファイルを提供する方法を示しています。
// 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
}});
});