Это 2013 год. Если вы собираетесь создавать веб-приложение, вы должны добавить в приложение возможности реального времени. Это стандарт. Meteor делает довольно хорошую работу, помогая вам быстро создавать и создавать приложения в режиме реального времени. Но метеор тесно связан с MongoDB, и это единственный способ добавить возможности в реальном времени. Иногда это излишне.
MongoDB идеально подходит для Meteor. Но нам не нужно использовать MongoDB для всех наших действий в реальном времени. Для некоторых проблем решения на основе обмена сообщениями работают очень хорошо. Это та же проблема, что и для pubnub и real-time.co .
Было бы здорово, если бы у нас в Meteor был гибридный подход к работе в реальном времени, сочетающий подход, основанный на коллекции MongoDB, и подход, основанный на обмене сообщениями. Таким образом, Meteor Streams был рожден для того, чтобы добавить эту передачу сообщений в режиме реального времени к Meteor.
Представляем метеорные потоки
Поток является основным строительным блоком метеорных потоков. Это EventEmitter в реальном времени. С помощью Stream вы можете передавать сообщения туда и обратно между подключенными клиентами. Это очень управляемо и имеет очень хорошую модель безопасности.
Давайте попробуем
Давайте создадим очень простое приложение для чата на основе браузера с Meteor Streams. Сначала мы создадим новое приложение Meteor:
1
|
meteor create hello-stream
|
Далее мы устанавливаем метеорные потоки из атмосферы:
1
|
mrt add streams
|
Затем нам нужно создать файл с именем chat.js
и поместить в следующий код:
01
02
03
04
05
06
07
08
09
10
11
12
|
chatStream = new Meteor.Stream(‘chat’);
if(Meteor.isClient) {
sendChat = function(message) {
chatStream.emit(‘message’, message);
console.log(‘me: ‘ + message);
};
chatStream.on(‘message’, function(message) {
console.log(‘user: ‘ + message);
});
}
|
Запустите ваше приложение с:
1
|
meteor
|
Ваше приложение теперь будет работать на — http://localhost:3000
.
Теперь у вас есть полнофункциональное приложение для чата. Чтобы начать чат, откройте консоль браузера и используйте метод sendChat
как показано ниже.
Давайте углубимся дальше
Довольно сложно понять Meteor Streams с помощью простого примера на основе консоли, подобного тому, который мы только что создали. Итак, давайте создадим полнофункциональное приложение для чата, чтобы лучше познакомиться с Meteor Streams.
Приложение
Приложение, которое мы создаем, является веб-приложением чата. Любой может общаться анонимно. Также пользователи могут зарегистрироваться и пообщаться в чате со своей личностью (именем пользователя). Он также имеет систему фильтрации, которая отфильтровывает плохие слова (ненормативную лексику).
В конце это будет выглядеть примерно так . Вы можете получить исходный код из github, чтобы увидеть окончательный результат.
Давайте создадим приложение
Давайте создадим стандартное приложение Meteor и установим метеорные потоки из атмосферы . Мы также добавим поддержку для начальной загрузки и учетных записей Meteor .
1
2
3
4
5
6
|
meteor create awesome-chat-app
cd awesome-chat-app
meteor remove insecure autopublish
meteor add bootstrap accounts-password accounts-ui
mrt add streams
rm awesome-chat-app.* //remove files added automatically
|
Давайте построим пользовательский интерфейс
Пользовательский интерфейс нашего приложения будет довольно простым. У нас есть div
показывающий сообщения чата и поле input
для ввода новых сообщений чата. Смотрите ниже полный HTML нашего интерфейса. Проверьте встроенные комментарии, если вам нужна помощь в понимании кода.
Добавьте следующий контент в client/home.html
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
<head>
<title>Awesome Chat App</title>
<style type=»text/css»>
#chat-message {
width: 500px;
height: 50px;
}
#messages {
width: 700px;
height: 300px;
border: 1px solid rgb(230, 230, 230);
margin: 0px 0px 10px 0px;
}
</style>
</head>
<body>
{{> mainBox}}
</body>
<!— Main Chat Window —>
<template name=’mainBox’>
<div class=’container’>
<h2>Awesome Chat App</h2>
<!— shows login buttons —>
{{loginButtons}}
{{> chatBox}}
</div>
</template>
<!— Chat Box with chat messages and the input box —>
<template name=’chatBox’>
<div id=’messages’>
{{#each messages}}
{{>chatMessage}}
{{/each}}
</div>
<textarea id=’chat-message’></textarea><br>
<button class=’btn btn-primary’ id=’send’>Send Chat</button>
</template>
<!— Template for the individual chat message —>
<template name=’chatMessage’>
<div>
<b>{{user}}:</b> {{message}}
</div>
</template>
|
Подключение нашего чата
Реактивность Метеора — потрясающая концепция и очень полезная. Теперь Метеоритные потоки не являются источником реактивных данных . Но он может хорошо работать только с локальными коллекциями для обеспечения реактивности .
Как следует из названия, только локальные коллекции не синхронизируют свои данные с сервером. Его данные доступны только внутри клиента (вкладка браузера).
Добавьте следующее содержимое в lib/namespace.js
чтобы создать нашу локальную коллекцию:
1
2
3
|
if(Meteor.isClient) {
chatCollection = new Meteor.Collection(null);
}
|
Теперь пришло время соединить наши шаблоны с коллекцией. Давайте сделаем следующее:
- Назначьте коллекцию помощнику
messages
в шаблонеchatBox
. - Сгенерируйте значение для помощника
user
в шаблонеchatMessage
. - Когда нажата кнопка «
Send Chat
, добавьте набранное сообщение чата в коллекцию.
Добавьте следующий контент в client/ui.js
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// assign collection to the `messages` helper in `chatBox` template
Template.chatBox.helpers({
«messages»: function() {
return chatCollection.find();
}
});
// generate a value for the `user` helper in `chatMessage` template
Template.chatMessage.helpers({
«user»: function() {
return this.userId;
}
});
// when `Send Chat` clicked, add the typed chat message into the collection
Template.chatBox.events({
«click #send»: function() {
var message = $(‘#chat-message’).val();
chatCollection.insert({
userId: ‘me’,
message: message
});
$(‘#chat-message’).val(»);
}
});
|
С этими изменениями вы сможете общаться, но сообщения отображаются только на вашем клиенте. Итак, давайте передадим оставшуюся часть работы Meteor Streams.
Давайте создадим поток
Мы будем создавать поток как на клиенте, так и на сервере (с одинаковым именем) и добавим необходимые разрешения.
Добавьте следующий код в lib/namespace.js
для создания потока:
1
|
chatStream = new Meteor.Stream(‘chat-stream’);
|
Одного создания потока недостаточно; нам нужно дать необходимые разрешения, которые позволяют клиентам общаться через него. Существует два типа разрешений (чтение и запись). Нам нужно учитывать событие, userId и subscriptionId при создании разрешения.
-
userId
— это userId клиента, подключенного к потоку. -
subscriptionId
— это уникальный идентификатор, созданный для каждого клиента, подключенного к потоку.
Для нашего приложения чата нам нужно предоставить любому пользователю, использующему приложение, полный доступ на чтение и запись к событию chat
. Таким образом, клиенты могут использовать его для отправки и получения сообщений чата.
Добавьте следующий код в server/permissions.js
:
1
2
3
4
5
6
7
|
chatStream.permissions.read(function(eventName) {
return eventName == ‘chat’;
});
chatStream.permissions.write(function(eventName) {
return eventName == ‘chat’;
});
|
Соединение потока с пользовательским интерфейсом
Теперь, когда у нас есть полностью работающий поток, давайте подключим его к пользовательскому интерфейсу, чтобы другие могли видеть отправляемые вами сообщения.
Первое, что нам нужно сделать, это добавить наши сообщения чата в поток, когда мы нажимаем кнопку « Send Chat
. Для этого нам нужно изменить код, связанный с событием нажатия кнопки « Отправить чат » (click #send), следующим образом (в client/ui.js
):
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
Template.chatBox.events({
«click #send»: function() {
var message = $(‘#chat-message’).val();
chatCollection.insert({
userId: ‘me’,
message: message
});
$(‘#chat-message’).val(»);
// == HERE COMES THE CHANGE ==
//add the message to the stream
chatStream.emit(‘chat’, message);
}
});
|
Затем нам нужно прослушать поток для события chat
и добавить сообщение в chatCollection
которое отображается в пользовательском интерфейсе, реактивно. Добавьте следующий код в файл client/ui.js
:
1
2
3
4
5
6
7
|
chatStream.on(‘chat’, function(message) {
chatCollection.insert({
userId: this.userId, //this is the userId of the sender
subscriptionId: this.subscriptionId, //this is the subscriptionId of the sender
message: message
});
});
|
Теперь нам нужно изменить логику, которая генерирует значение для помощника user
в шаблоне chatMessage
следующим образом:
- Зарегистрированный пользователь —
user-<userId>
- Анонимный пользователь —
anonymous-<subscriptionId>
Измените код для помощника user
в шаблоне chatMessage
чтобы отразить вышеуказанные изменения (в client/ui.js
):
1
2
3
4
5
6
|
Template.chatMessage.helpers({
«user»: function() {
var nickname = (this.userId)?
return nickname;
}
});
|
Отображение имени пользователя вместо userId
Отображение только userId
не очень полезно. Итак, давайте изменим его, чтобы отобразить фактическое имя пользователя. Здесь мы будем использовать Meteor Pub / Sub, чтобы получить имя пользователя для данного идентификатора пользователя.
Прежде всего, давайте настроим учетные записи Meteor для принятия имени пользователя при создании пользователя. Добавьте следующий код в client/users.js
:
1
2
3
|
Accounts.ui.config({
passwordSignupFields: «USERNAME_ONLY»
});
|
Тогда давайте создадим публикацию для получения пользователя. Добавьте следующий код в server/users.js
. Он просто возвращает имя пользователя для данного userId.
1
2
3
|
Meteor.publish(«user-info», function(id) {
return Meteor.users.find({_id: id}, {fields: {username: 1}});
});
|
Теперь нам нужно создать подписку на клиенте для каждого интересующего нас пользователя. Мы сделаем это внутри метода. Кроме того, после того как мы получим имя пользователя, его необходимо назначить переменной сеанса. Затем мы можем использовать переменную сеанса внутри помощника user
чтобы получить имя пользователя реактивно.
Добавьте следующий код в client/users.js
:
1
2
3
4
5
6
7
8
9
|
getUsername = function(id) {
Meteor.subscribe(‘user-info’, id);
Deps.autorun(function() {
var user = Meteor.users.findOne(id);
if(user) {
Session.set(‘user-‘ + id, user.username);
}
});
}
|
Наконец, давайте chatMessage
помощник user
в шаблоне chatMessage
чтобы получить имя пользователя из сеанса (в client/ui.js
):
01
02
03
04
05
06
07
08
09
10
11
12
|
Template.chatMessage.helpers({
«user»: function() {
if(this.userId == ‘me’) {
return this.userId;
} else if(this.userId) {
getUsername(this.userId);
return Session.get(‘user-‘ + this.userId);
} else {
return ‘anonymous-‘ + this.subscriptionId;
}
}
});
|
Фильтрация плохих слов
Наше приложение-чат поможет скрыть ненормативную лексику Если кто-то пытается отправить сообщение с плохими словами, мы должны отфильтровать их. Метеоритный поток имеет функцию под названием фильтры , которая предназначена для этого. Давайте посмотрим, как мы можем отфильтровать слово fool
из любого сообщения чата.
Добавьте следующий код в server/filters.js
:
01
02
03
04
05
06
07
08
09
10
11
|
chatStream.addFilter(function(eventName, args) {
if(eventName == ‘chat’) {
var message = args[0];
if(message) {
message = message.replace(/fool/ig, ‘****’);
}
return [message];
} else {
return args;
}
});
|
Не стесняйтесь добавлять свои собственные фильтры.
Наше приложение для чата завершено. Вы можете увидеть живую версию приложения на http://streams-chat.meteor.com . Кроме того, исходный код приложения доступен на Github.
Вывод
В этом уроке мы создали приложение чата, используя local only collections
для добавления в реактивность, и использовали Meteor Pub/Sub
для получения имени пользователя. Надеюсь, вы сможете увидеть, насколько хорошо Meteor Streams может работать с существующими функциями Meteor. Тем не менее, это всего лишь введение в метеорные потоки, для дополнительных ресурсов, проверьте следующие ссылки: