4. PubSub
• Издатель (Publisher)
– Генерирует данные одного типа
– Издает только одну газету
– Издателей может быть много
• Подписчики (Subscribers)
– Подписываются на данные издателя
– Могут отписаться в любой момент
• Данные – поток
– Поздно подписался – упустил данные
– Объем и частота публикаций задается издателем
4
5. PubSub – пример
var PubSub = function () {
this.readers = [];
};
PubSub.prototype = {
pub: function (data) {},
sub: function (callback) {},
unsub: function (callback) {}
};
// function callback(data) {}
5
6. PubSub – особенности
• Самая простая реализация
• Только 1 тип данных
– А хочется еще и "Мурзилку" получать
• Нужно напрямую общаться с объектом
6
8. Event Emitter
• Имеет много названий
• Издатель
– Генерирует данные разных типов
– Издает газеты и журналы
– Издателей может быть много
• Подписчики
– Подписываются на данные любого типа в любом количестве
– Могут отписаться в любой момент
• Данные – поток
– Поздно подписался – упустил данные
– Объем и частота публикаций задается издателем
8
9. Event Emitter – пример
var EventEmitter = function () {
// events = {"event_name": []};
this.events = {};
};
EventEmitter.prototype = {
emit: function (event, data) {},
on: function (event, callback) {},
off: function (event, callback) {}
};
// function callback(data) {}
9
10. Event Emitter – особенности
• Много разных типов данных
• Нужно иметь ссылку на EventEmitter
10
12. Event Manager
• Имеет много названий
• Своеобразная шина данных
• Единственный издатель
– Генерирует данные разных типов
• Подписчики
– Подписываются на данные любого типа в любом количестве
– Могут отписаться в любой момент
• Данные – поток
– Поздно подписался – упустил данные
– Объем и частота публикаций задается издателем
12
13. Event Manager – пример
Похож на Event Emitter, но это Синглентон
var EventManager = {
events: {},
emit: function (event, data) {},
on: function (event, callback) {},
off: function (event, callback) {}
};
// function callback(data) {}
13
14. Event Manager – особенности
• Много разных типов данных
• Об этом объекте знают все
14
15. Дополнительные фичи
Управление событиями, namespace
Накопление данных
События на дереве DOM
Делегирование событий
Фильтрация событий
18. Управление событиями
• Группировка событий
– namespace
• Легкое удаление событий
– Удаление события без callback
– Удаление по дескриптору
18
19. Управление событиями – пример
jQuery 1.8
var handler = function () {};
$('body').on('click.ns', handler);
$('body').off('click', handler); // не удобно
$('body').off('click'); // все click
$('body').off('.ns'); // весь namespace
$('body').off(); // все события
$('body').off('**'); // все делегированные
19
20. Накопление данных
• Опоздал с подпиской – ничего не получил
– Это не удобно
• Пользователь желает получить все
– Всю подписку журналов с нуля
• Как только подписался – сразу получил
• Похоже на Promise
20
21. Накопление данных – пример
jQuery DOMReady
$(function () {
$(function () {
console.log('Tada!');
});
});
21
22. Накопление данных – пример
jQuery Ajax#done
var data = $.get('/');
data.done(function () {
data.done(function () {
console.log('Tada!');
});
});
22
29. Event bubbling в jQuery
Event bubbling – фаза по умолчанию в jQuery
// jQuery 1.7 .on()
$('.b-form-button').on('click', function (event) {
console.log(this); // .b-form-button element
});
// Хэлперы
$('.b-form-button').click(function (event) {
console.log(event);
});
http://api.jquery.com/on/
http://api.jquery.com/category/events/
29 http://api.jquery.com/category/events/event-object/
30. Event bubbling в i-bem
Функция bindTo()
BEM.DOM.decl('b-form-input', {
onSetMod : {
'js' : {
'inited' : function () {
this
.bindTo(this.elem('input'), {
'focus' : this.onFocus,
'blur' : this.onBlur
});
}
}
}
});
http://bem.github.com/bem-bl/sets/common-
30
desktop/i-bem/i-bem.ru.html
31. Не всплывающие события
• var itBubbles = event.bubbles;!
• Специфичные события для 1 элемента
– submit, focus, blur, load, unload, change, reset, scroll
• Некоторые события мутаций DOM
– DOMFocusIn, DOMFocusOut, DOMNodeRemoved
https://developer.mozilla.org/en-US/docs/
31 Mozilla_event_reference
32. Особенности
• Фазы Capturing & Bubbling идут
одновременно
– Чередуются capturing, bubbling
• Каждый обработчик получает новый инстанс
объекта Event
32
http://jsfiddle.net/h2nJU/2/
42. Профит делегирования
• Меньше обработчиков событий
– Экономия памяти
– Меньше утечек памяти
• Проще работать с динамическими
элементами
42
43. Особенности делегирования
• Если событие не всплывает – ничего не
получится
• Нужно максимально ограничивать событие
– Необходимо выбрать наиболее близкого делегата
• Возможны частые ложные вызовы события
– Большие затраты на вызов функции
• Ограничить делегирование у частых
событий
– mousemove
• Не использовать делегирование если
элемент 1
43
48. Прерывание действия по умолчанию
• Действие по умолчанию
– Переход по ссылке
– Раскрытие <select>
– Сабмит формы
– Фокус в инпут
– Снятие фокуса
• event.preventDefault()
– Перерывает это действие
• Некоторые действия прервать нельзя
– var isCanPrevent = event.cancelable;
– resize, scroll, focus, error, load, unload, DOM*, …
https://developer.mozilla.org/en-US/docs/DOM/
48 event.preventDefault
49. Прерывание событий jQuery
$('.b-link').click('click', function (event) {
return false; // preventDefault+stopPropagation
});
$('.b-form').click('submit', function (event) {
return isValid(this); // this - .b-form
});
$('.b-link').click('click', function (event) {
event.preventDefault();
event.stopPropagation();
});
http://api.jquery.com/on/
49
http://api.jquery.com/live/
62. Событие геттер
Вариант не удачного использования событий
DataObject.on('someData', function (data) {
console.log(data);
});
DataObject.trigger('giveMe:someData');
62
71. Накладные расходы
• Событие – функция
– n объектов, k ресурсов = n*k функций
– функция занимает ресурсы
– лишние скоупы, сборка мусора и JIT-компиляция
– вызов кучи функций
– утечки памяти
71
73. Не блокирующий I/O
• Дефрагментация времени блокировок
– Более плотная загрузка процесса
• Выгодно применять, когда время I/O больше
времени обработки данных
• Меньше проблем с разделяемой памятью
73
74. Слабое связывание
• Элементы не знают о программе
• Элементы общаются только событиями
• Меньше разделенной памяти
– Меньше проблем синхронизации
74
76. Заключение
• События
– PubSub
– Event Emitter
– Event Manager
• Фичи событий
– namespace
– накопление данных
• DOM события
– Event Bubbling
– Делегирование
– Прерывание события
– Отмена действия по умолчанию
• Фильтрация
76
77. Михаил Давыдов
Разработчик JavaScript
azproduction@yandex-team.ru
azproduction
77
Спасибо