#javascript #signalr
#javascript #signalr
Вопрос:
Каков правильный шаблон JavaScript для подключения к SignalR и постоянного поддержания ссылки, пока они находятся на странице, независимо от того, переводят ли пользователи свои компьютеры в спящий режим или имеют прерывистые подключения к Интернету.
В документации просто сказано использовать:
$.connection.hub.start()
.done(function(){ console.log('Now connected, connection ID=' $.connection.hub.id); })
.fail(function(){ console.log('Could not Connect!'); });
});
Но, похоже, это не учитывает разъединения и другие проблемы.
Кроме того, он не улавливает проблему истечения срока действия сеанса и требует повторного входа в систему.
Комментарии:
1. Этот вопрос основан на мнениях и, следовательно, не по теме для Stack Overflow.
2. Как вызов API способом обработки ошибок является вопросом, основанным на мнении ?!?
3. Какой правильный шаблон JavaScript для подключения к SignalR …? Поскольку не существует единого «правильного» шаблона для подключения к SignalR (концентратор, постоянное соединение и т.д.), Это вопрос мнения, который является «наиболее правильным».
4. Я должен не согласиться, он запрашивает ответ на конкретную проблему, которая не является стандартной реализацией singlar.
Ответ №1:
Учитывая, что SignalR является клиент-серверным решением на основе соединения, вы не можете рассчитывать на длительные устойчивые открытые соединения. Итак, как написал Келсо Шарп в своем ответе, единственная хорошая вещь, которую вы можете сделать, это управлять событиями жизненного цикла соединения.
Ознакомьтесь с документацией для всех событий жизненного цикла подключения SignalR: https://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client#connectionlifetime
Итак, если мы не сосредоточим наше внимание на том, как создать постоянное соединение, которое никогда не дает сбоев, мы могли бы вместо этого сосредоточиться на том, чтобы создать у пользователя впечатление об этом, хитро управляя отключениями, перезагрузками и тому подобным в фоновом режиме.
Вот диаграмма, показывающая, как я бы это настроил, хотя вы не указали, что заставляет ваш концентратор передавать данные клиентам, но я представляю, что это может быть что-то вроде этой диаграммы. Идея здесь в том, что вы передаете одно и то же состояние какому-то поставщику состояния, то есть кешу, хранилищу веб-api, чтобы у вас был весь набор данных, доступных в любой момент времени. Когда пользовательский интерфейс загружается или отключается, он должен отправить запрос этому поставщику для восстановления состояния, а затем он должен повторно подключиться к концентратору.
Если возникает проблема с согласованностью данных, вы могли бы выполнить управление версиями состояния, сохранить локальную копию в пользовательском интерфейсе, а затем выполнить аудит при повторном подключении. Таким образом, вы могли бы видеть, пропустили ли вы что-то, и в этом случае вы бы отправляли запросы на догонялки государственному провайдеру.
Для обработки событий вам просто нужно подключить некоторые функции на стороне вашего клиента: // это вызовет все изменения состояния во время цикла подключения:
$.connection.hub.stateChanged(function (change) {
if (change.newState === $.signalR.connectionState.reconnecting) {
console.log("liveFeed is reconnecting!");
}
else if (change.newState === $.signalR.connectionState.connected) {
console.log("liveFeed is connected!");
}
});
// это срабатывает при отключении от концентратора.
$.connection.hub.disconnected(function () {
console.log('Connection disconnected')
});
Комментарии:
1. У вас есть какие-либо подробности о том, когда
disconnected
вызывается по отношению кreconnecting
. И гарантировано ли, что он всегда будет пытаться повторно подключиться до конца дней? Если да, то какова задержка при попытках? И как я мог бы принудительно выполнить попытку? Кроме того, получаете ли вы уведомление о неудачной попытке повторного подключения?2. Как обрабатывать истечение срока действия сеанса?
3. @Cine хорошо, что вы прочитали документацию, в которой перечислены все события жизненного цикла, вы можете ожидать, что они будут запускаться при возникновении этих событий. Что касается повторных попыток и тому подобного, есть пара шаблонов, которые вы могли бы опробовать в базовом шаблоне повторных попыток с задержкой между попытками. Тогда я бы настоятельно рекомендовал использовать увеличивающуюся задержку, если повторные попытки последовательно завершаются неудачей. Или вы могли бы попробовать шаблон автоматического отключения, он немного более продвинутый, и это может быть не то, что вы ищете в данной ситуации.
Ответ №2:
Единственный способ, которым, на мой взгляд, это можно сделать, — это использовать объединительную плату, которая хранит информацию о соединении каждого подключенного клиента. Тем не менее, они никогда не будут «оставаться на связи», если они потеряли Интернет или переходят в спящий режим, все, что вы можете сделать, это «переподключиться», вам придется постоянно хранить любую информацию о состоянии в случае отключения, вы не можете сделать это в событии «disconnect», потому что к тому времени, вероятно, будет слишком поздно. Одним из вариантов было бы непрерывно передавать информацию о состоянии в кэш redis и периодически отправлять ее на эту заднюю плоскость с более разумными интервалами, или когда отключенный даже срабатывает.
Комментарии:
1. Цель не в том, чтобы они никогда не отключались, цель в том, чтобы пользовательский интерфейс никогда не ВИДЕЛ отключения (за исключением случая, когда требуется снова войти в систему). Т.е. когда пользовательский интерфейс активен и имеет входящее соединение, он подключен.
2. Я полагаю, что это решение позволит достичь этого, просто нужно убедиться, что вы управляете состоянием пользовательского интерфейса, и, делая это, вы можете извлекать данные из кэша redis, если произойдет сбой в подключении.
3. правильно, с помощью кэша redis у вас всегда есть ваше текущее состояние, поэтому вы можете сделать так, чтобы оно выглядело так, как будто они никогда не отключались.
Ответ №3:
Выяснил, как выполнить истечение срока действия сеанса, обернув все вызовы на сервер повторной попыткой:
function callServer(call) {
function err(r?: Error) {
var output = $.Deferred();
if (r amp;amp;
r.message amp;amp;
(r.message.startsWith("Caller is not authorized to invoke the") ||
r.message.startsWith("The user identity cannot change during "))) {
$('#login-dialog')
.one('hide.bs.modal',
() => {
hub.connection.stop();
$.connection.hub.start()
.then(() => hub.server.run(call))
.then(output.resolve, output.reject);
})
.modal('show');
return output;
}
// ReSharper disable once SuspiciousThisUsage
return output.rejectWith(this, <any>arguments);
}
return $.connection.hub.start()
.then(() => hub.server.run(call))
.then(null, err);
}
Это предполагает наличие модального диалогового окна начальной загрузки #login-dialog
, которое при закрытии означает, что он обработал повторный вход в систему.