Backbone Radio
Backbone Radio предоставляет простую поддержку ряда шаблонов обмена сообщениями для Backbone и Marionette. Это обеспечивается с помощью двух основных конструкций:
- События — запускают события на глобальном объекте
- Запросы — глобальная реализация запроса/ответа
Radio использует эти две конструкции и добавляет реализацию канала — предоставляя пространства имён для событий и запросов. Короче говоря, Radio — это глобальная, именованная система шины сообщений, предназначенная для того, чтобы два по-другому не связанных объекта могли общаться и обмениваться информацией.
Индекс документации
Концепции Radio
Блоки сообщений Radio раскрывают некоторые основные концепции:
-
Channel— механизм пространства имён. -
Event— оповещение других частей приложения о том, что произошло событие. -
Request— выполнение отдельных функций в другой части вашего приложения.
Канал
channel — это главная причина использования Radio в качестве агрегатора событий — он обеспечивает чистую точку для разделения глобальных событий. Для получения канала используйте Radio.channel(channelName):
import Radio from 'backbone.radio';
const myChannel = Radio.channel('basic');
myChannel.on('some:event', function() {
// ...
});
Канал доступен во всех частях вашего приложения. Просто импортируйте Radio и вызовите channel() для добавления слушателей, вызова обратных вызовов или отправки запросов.
import Radio from 'backbone.radio';
const someChannel = Radio.channel('basic'); // Exactly the same channel as above
someChannel.trigger('some:event'); // Will fire the function call above
Событие
Radio Event работает точно так же, как обычные события Backbone Events , такие как модель/коллекция. На самом деле, он использует миксин Backbone.Events внутри, предоставляя свой API:
-
channel.on('event', callback, [context])— когдаeventсработает, вызовитеcallback -
channel.once('event', callback, [context])— то же, что иon, но срабатывает только один раз -
channel.off('event')— прекратить прослушивание события -
channel.trigger('event', ..args)— вызываетeventи передает аргументы в полученныйcallback
События обычно используются для оповещения других частей системы о том, что произошло событие. Например, срок действия входа пользователя истек или пользователь выполнил определённое действие.
Поскольку Radio может быть импортирован в любом месте, мы можем использовать его в качестве глобального агрегатора событий:
import Radio from 'backbone.radio';
const myChannel = Radio.channel('star');
myChannel.on('left:building', function(person) {
console.log(person.get('name') + ' has left the building!');
});
const elvis = new Bb.Model({name: 'Elvis'});
myChannel.trigger('left:building', elvis);
myChannel.off('left:building');
Как и Backbone Events, Radio соблюдает обработчик listenTo:
import { MnObject } from 'backbone.marionette';
import Radio from 'backbone.radio';
const starChannel = Radio.channel('star');
const Star = MnObject.extend({
initialize() {
this.listenTo(starChannel, 'left:building', this.leftBuilding);
this.listenTo(starChannel, 'enter:building', function(person) {
console.log(person.get('name') + ' has entered the building!');
});
},
leftBuilding(person) {
console.log(person.get('name') + ' has left the building!');
}
});
Обратите внимание, что обработчик событий может быть определён как метод, как используется для 'left:building' события, или в строке, как используется в 'enter:building'.
Как и в Backbone, обработчик событий вызывается с this , связанным с экземпляром Star. Обратитесь к документации Backbone для получения полного списка методов обработки событий.
Когда использовать события
Событие — это просто уведомление о том, что что-то произошло, и вы можете или не хотите, чтобы другие объекты в вашем приложении реагировали на это. Несколько ключевых принципов, которые следует иметь в виду:
- Если вы не знаете, что может действовать на событие, или вам всё равно, используйте
Event - Если вы обнаруживаете, что вызываете его действием, которое произошло, используйте
Event - Если для многих объектов приемлемо выполнять действие, используйте
Event - Если вас не волнует, что объекты не отреагируют, используйте
Event
Если ваш случай использования здесь не описан, подумайте, хотите ли вы вместо этого использовать запрос.
Запрос
API запросов предоставляет единообразный способ для несвязанных частей системы общаться друг с другом. Например, отображение уведомлений в ответ на системную активность. Для добавления слушателя к каналу запросов используйте reply или replyOnce для добавления слушателя, который сразу отсоединяется после одного вызова.
Как и в запросе, любые аргументы, передаваемые в channel.request , будут переданы в обратный вызов.
import { MnObject } from 'backbone.marionette';
import Radio from 'backbone.radio';
const channel = Radio.channel('notify');
const Notification = MnObject.extend({
initialize() {
channel.reply('show:success', this.showSuccessMessage);
channel.reply('show:error', function(msg) {
// ...
});
},
showSuccessMessage(msg) {
// ...
}
});
Например, когда синхронизация модели завершается ошибкой:
import { View } from 'backbone.marionette';
import Radio from 'backbone.radio';
const channel = Radio.channel('notify');
const ModelView = View.extend({
modelEvents: {
error: 'showErrorMessage'
},
showErrorMessage() {
channel.request('show:error', 'An error occurred contacting the server');
}
});
Теперь, всякий раз, когда модель, присоединённая к этому представлению, не может синхронизироваться с сервером, мы можем отобразить сообщение об ошибке пользователю.
Возвращение значений из ответа
API запросов также может возвращать значения, что делает его чрезвычайно полезным для доступа к объектам, которые в противном случае трудно получить. Например, предположим, что мы прикрепляем текущего вошедшего в систему пользователя к объекту Application и хотим узнать, всё ли с ним в порядке.
import { Application } from 'backbone.marionette';
import Radio from 'backbone.radio';
const channel = Radio.channel('user');
const App = Application.extend({
initialize() {
channel.reply('user:loggedIn', this.isLoggedIn);
},
isLoggedIn() {
return this.model.getLoggedIn();
}
});
Затем, из другого представления, вместо того, чтобы пытаться найти модель User. мы просто request её:
const Radio = require('backbone.radio');
const channel = Radio.channel('user');
const loggedIn = channel.request('user:loggedIn'); // App.model.getLoggedIn()
Когда использовать запросы
Запрос, как вы можете догадаться, — это запрос информации или выполнение действия. Вы, вероятно, захотите использовать запросы, когда:
- Вы называете запрос действием для выполнения, например
show:notification - Вы хотите получить возвращаемое значение запроса
- Вы хотите вызвать ровно одну функцию
В дополнение к этой документации, документация Radio доступна на Github.
Интеграция с Marionette
Классы Application и MnObject предоставляют привязки для автоматического добавления слушателей событий и/или обработчиков запросов к вашим экземплярам объектов. Это работает с привязанным channelName , позволяя нам предоставлять слушателей с помощью свойств radioEvents и radioRequests.
Ошибки Будет выброшено исключение при использовании интеграции радио, если backbone.radio не настроен как зависимость.
API
-
channelName— определяет канал Radio, который будет использоваться для запросов и/или событий -
getChannel()— возвращает экземпляр Radio.Channel с использованиемchannelName -
radioEvents— определяет хэш событий с событиями, которые необходимо прослушать, и соответствующими обработчиками -
radioRequests— определяет хэш событий с запросами, на которые необходимо ответить, и соответствующими обработчиками
Примеры
Прослушивание событий
import { MnObject } from 'backbone.marionette';
const Star = MnObject.extend({
channelName: 'star',
radioEvents: {
'left:building': 'leftBuilding'
},
leftBuilding(person) {
console.log(person.get('name') + ' has left the building!');
}
});
Это даёт нам чёткое определение того, как этот объект взаимодействует с каналом радио star.
Отвечать на запросы
import { MnObject } from 'backbone.marionette';
const Notification = MnObject.extend({
channelName: 'notify',
radioRequests: {
'show:success': 'showSuccessMessage',
'show:error': 'showErrorMessage'
},
showSuccessMessage(msg) {
// ...
},
showErrorMessage(msg) {
// ...
}
});
Теперь у нас есть чёткий API для взаимодействия с Notification по всему приложению. Не забудьте определить channelName в своём определении MnObject.
Как и в обычном запросе/ответе, мы можем возвращать значения из этих связанных обработчиков:
import { Application } from 'backbone.marionette';
const App = Application.extend({
channelName: 'user',
radioRequests: {
'user:loggedIn': 'isLoggedIn'
},
isLoggedIn() {
return this.model.getLoggedIn();
}
});
События и запросы
import { MnObject } from 'backbone.marionette';
const NotificationHandler = MnObject.extend({
channelName: 'notify',
radioRequests: {
'show:success': 'showSuccessMessage',
'show:error': 'showErrorMessage'
},
radioEvents: {
'login:user': 'showProfileButton',
'logout:user': 'hideProfileButton'
},
showSuccessMessage(message) {
// ...
},
showErrorMessage(message) {
// ...
},
showProfileButton(user) {
// ...
},
hideProfileButton(user) {
// ...
}
});
В несвязанном модуле:
import Radio from 'backbone.radio';
import User from './models/user';
const notifyChannel = Radio.channel('notify');
const userModel = new User();
// The following will call Notification.showErrorMessage(message)
notifyChannel.request('show:error', 'A generic error occurred!');
// The following will call Notification.showProfileButton(user)
notifyChannel.trigger('login:user', userModel);
© 2017 Muted Solutions, LLC
Licensed under the MIT License.
https://marionettejs.com/docs/v4.0.0/backbone.radio.html