На работе почувствовал, что проект недостаточно «отзывчив».
Есть интерфейс со списком элементов. Каждый элемент характеризуется набором свойств, в т.ч. у него меняется статус. Редактирование элемента происходит в новом окне. Следовательно, отредактировав его, и переключившись на вкладку со списком, хочется видеть, что он уже изменился, стал не такой как прежде [, бросил пить, курить, и, вообще, теперь хороший человек :)].
В качестве back-end'а используется iis с asp.net mvc. Первой итерацией решил попробовать polling/long polling техники, как максимально простые, использующие стандартные асинхронные запросы к серверу.
Опирался на метод, описанный Клэем в статье
WebSockets is cool, but what can you do today?В клиенте делал $.post и прицеплял таймер:
setTimeout(function () {
getMessages();
}, 500)
На уровне сервера: создал асинхронный контроллер с менеджером количества запросов.
Всё бы хорошо, но где-то в таймере я ошибся. Страница периодически подвисала на 0.5-2 мин, данных из контроллера не приходило.
Вопрос этот отложил, до будущих свободных времён.
На курсе по javascript предоставилась возможность поинтересоваться у
Миши. Он посоветовал
веб-сокеты, которые я отмёл в начале из-за частичной поддержки в браузерах (надо включать вручную, т.к. старые версии протокола не безопасны). Привёл пример использования в Node.js (
socket.io) - там это делается в несколько строк, быстро и просто.
Незащищённую версию протокола поддерживают все основные браузеры, что не фатально для текущих дел, поэтому всё-таки решил попробовать. Поиск выдал несколько библиотек для работы в среде .net, по гитхабу сравнил уровень поддержки, документации и дату последних коммитов. Выбор пал на
SignalR. По мере доступности использует технологии: WebSockets - Server Sent Events - Forever Frame - Long polling.
Инициализация и отправка сообщений из клиента реализуется просто:
$(function () {
// Proxy created on the fly
var signal = $.connection.signal;
// Call the chat method on the server
//do something
var msgVal = ...
// Start the connection
$.connection.hub.start(function () { signal.send(msgVal) });
});
На сервере класс выглядит ещё проще:
[HubName("signal")]
public class signal : Hub
{
public void Send(string message)
{
//Call the addMessage method on all clients.
Clients.addMessage(message);
}
}
Всё бы хорошо, но возникла необходимость создавать сообщения и на сервере. Следуя
документации, в версии 0.5 это делается вызовом контекста соответствующего хаба в контроллере:
var context = GlobalHost.ConnectionManager.GetHubContext();
context.Clients.say(message);
Но вызова не происходит. В трекере уже создана
задача. Посмотрел stackoverflow, в одном из ответов, как решение,
предложили вызывать статический метод из самого класса хаба, где динамически вызывается метод addMessage. После замены на context.Clients.addMessage(message), сообщения пошли:)
P.S. Вводная лекция Дэмиана, разработчика SignalR
vimeo.com/43659069.