Шаблон посредника в вопросах JavaScript - PullRequest
6 голосов
/ 04 августа 2011

Я создаю своего рода библиотеку на основе посредника для моей работы. Мы создали много приложений, поэтому я хотел что-то, что можно легко взять и изменить для каждого приложения. Я также хочу, чтобы было достаточно просто создавать «виджеты» (из-за отсутствия лучшего термина) и легко удалять их, не беспокоясь о том, чтобы что-то сломать. Многие из этих приложений, которые мы делаем, также доступны сторонним разработчикам, создающим приложения или виджеты для приложений.

Вот так я и наткнулся на образец посредника. Я написал что-то, что работает примерно так:

//Extend
Core.extend('widget',function(params){
  alert(params.message);
});

//Load it
Core.load('widget',{message:'Hello World'});

//Remove it
Core.remove('widget');

У меня есть 3 вопроса:

  1. Как вы должны / должны иметь дело с манипулированием DOM в этом паттерне с помощью JavaScript? Я не хочу, чтобы разработчики возились с DOM за пределами своего виджета.

  2. Как вы должны обрабатывать запросы AJAX? Стоит ли вообще что-то делать? Если вы просто предложите AJAX / JSONP-вызов в библиотеке (Core в этом примере).

  3. Мой самый большой вопрос, как вы на самом деле взаимодействуете с другими виджетами? Я не хочу тесно связываться (очевидно), но я не понимаю, как вы будете взаимодействовать с другим виджетом. Например, допустим, у вас есть текстовое поле, и при отправке оно отправляет его в БД. Как может другой виджет, давайте назовем его виджетом «временная шкала», теперь, когда он был представлен, и затем обновим временную шкалу с текстом из виджета текстового поля?

=== UPDATE ===

Я закончил тем, что написал это:

http://oscargodson.github.com/Core.js/

1 Ответ

3 голосов
/ 20 сентября 2011

Виджеты взаимодействуют с виджетами: я только что закончил создание этого несколько дней назад. Я посмотрел, как вы это реализовали, и вот несколько дополнительных идей для вас.

Созданная вами система push-уведомлений очень похожа на систему событий jQuery DOM, благодаря которой произвольные события могут передаваться и приниматься. Я немного использовал эту систему для разработки разорванных виджетов, однако нашел ее весьма желательной, потому что в конечном итоге «толкает» (события, испускает, что угодно) из контекста - как в слушателях, понятия не имею, если это даже в рамках того, что они хотели, пока они не опросят событие.

Рассмотрим, например, если каждый элемент пользовательского интерфейса на веб-странице был виджетом в вашей системе. Там будет легко 30+ на одной странице. Если каждый из них должен был нажать «загруженное» сообщение, остальные 29 должны его получить. Кроме того, как вы упомянули, сторонние разработчики будут разрабатывать для этой системы. Затем им приходится обременять себя фильтрацией сообщений, которые они не хотят получать.

Подход, который я использовал в своей последней системе связи виджетов, - это то, что я называю подходом "pubstring" / "substring" (и, честно говоря, я уверен, что кто-то еще придумал эту идею до меня и имеет какое-то круто звучащее название для него). По сути, всякий раз, когда виджет «толкает», этот толчок превращается в строку, которая содержит: область (контекст), тип виджета, конкретный идентификатор виджета, каким бы он ни был, и конкретное сообщение.

Так скажем, например, виджет с идентификатором 45, типа «твит-лист», в области «пользовательские» отправляет сообщение «загружен». Строка паба будет тогда отображаться в: custom.tweet-list.45.loaded.

Когда подписки размещаются, они вводятся через хеш-таблицу, которая может дополнительно содержать значения для 4 атрибутов (вы можете легко добавить больше, кроме имеющейся у меня области / типа / идентификатора / сообщения). Слушание тогда будет таким:

listen({ realm: 'custom', type: 'whatever' }, f); // (where 'f' is a function)

Часть слушателя вашей платформы может превратить эту хеш-таблицу в «подстроку», которая будет регулярным выражением, выражающим фильтры, для которых она представляет:

custom\.whatever\.[^\.]+\.[^\.]+

Это регулярное выражение хранится в виде скомпилированного регулярного выражения в некотором скрытом массиве ...

__subscriptions.push(new RegExp(subString));

Затем всякий раз, когда что-то выдвигается (то есть публикуется), платформа в основном циклически перебирает массив __subscription, запускает .test каждой сохраненной подстроки (regex) и выполняет обратный вызов для этой подстроки, если совпадает.

Используя эту систему, можно применять неограниченное количество отфильтрованных слушателей, и слушатели знают, что они получают уведомления только в тех контекстах, которые им интересны.

Примеры:

// Listen for all messages by widget ID #99
listen({ id: 99 } ,f);

// Listen for all messages by widgets in realm clientB
listen({ realm: 'clientB' }, f);

// Listen for the data-received push of widgets whose type is tweet-list
listen({ type: 'tweet-list', message: 'data-received' }, f);

Поскольку регулярное выражение на самом деле является просто конкатенацией, оно также может быть включено в фильтр.

// Listen for any data- message
listen({ message: 'data-[^\.]+' }, f);

Прелесть этой системы в том, что вы можете сохранить свой текущий интерфейс, чтобы "все было просто" и просто проверить строку или хэш-таблицу для argument[0]. Другими словами ..

// This
listen('loaded', f);

// Could be equivalent to this on the backend:
listen({ message: 'loaded' }, f);

Я знаю, что это было долго, но надеюсь, что это дало вам некоторые идеи.

...