ASP.NET Core SignalR JavaScript client
Autor: Rachel Appel
Klientská knihovna ASP.NET Core SignalR JavaScript umožňuje vývojářům volat kód centra na straně SignalR serveru.
SignalR Instalace balíčku klienta
Klientská SignalR knihovna JavaScriptu se doručí jako balíček npm . Následující části popisují různé způsoby instalace klientské knihovny.
Instalace pomocí npm
Z konzoly Správce balíčků spusťte následující příkazy:
npm init -y
npm install @microsoft/signalr
npm nainstaluje obsah balíčku do složky node_modules\@microsoft\signalr\dist\browser . Vytvořte složku wwwroot/lib/signalr. signalr.js
Zkopírujte soubor do složky wwwroot/lib/signalr.
Odkazovat na javascriptového SignalR klienta v elementu <script>
. Příklad:
<script src="~/lib/signalr/signalr.js"></script>
Použití sítě pro doručování obsahu (CDN)
Chcete-li použít klientskou knihovnu bez předpokladu npm, odkazujte na kopii klientské knihovny hostované v CDN. Příklad:
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>
Klientská knihovna je k dispozici v následujících sítích CDN:
Instalace pomocí nástroje LibMan
Knihovnu LibMan lze použít k instalaci konkrétních souborů klientské knihovny z klientské knihovny hostované v CDN. Například do projektu přidejte pouze minifikovaný javascriptový soubor. Podrobnosti o tomto přístupu najdete v SignalR tématu Přidání klientské knihovny.
Připojení k centru
Následující kód vytvoří a spustí připojení. Název centra nerozlišuje velká a malá písmena:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
// Start the connection.
start();
Připojení mezi zdroji (CORS)
Prohlížeče obvykle načítají připojení ze stejné domény jako požadovaná stránka. Existují však situace, kdy se vyžaduje připojení k jiné doméně.
Při provádění požadavků mezi doménou musí kód klienta místo relativní adresy URL použít absolutní adresu URL. U žádostí mezi doménou přejděte .withUrl("/chathub")
na .withUrl("https://{App domain name}/chathub")
.
Aby se zabránilo škodlivému webu ve čtení citlivých dat z jiného webu, jsou ve výchozím nastavení zakázaná připojení mezi zdroji. Pokud chcete povolit žádost mezi zdroji, povolte CORS:
using SignalRChat.Hubs;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddSignalR();
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins("https://example.com")
.AllowAnyHeader()
.WithMethods("GET", "POST")
.AllowCredentials();
});
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
// UseCors must be called before MapHub.
app.UseCors();
app.MapRazorPages();
app.MapHub<ChatHub>("/chatHub");
app.Run();
UseCors musí být volána před voláním MapHub.
Metody centra volání z klienta
Klienti JavaScriptu volají veřejné metody v centrech prostřednictvím metody vyvolání HubConnection. Metoda invoke
přijímá:
- Název metody centra.
- Všechny argumenty definované v metodě centra.
V následujícím zvýrazněném kódu je SendMessage
název metody v centru . Druhý a třetí argument předaný pro invoke
mapování na metody user
centra a message
argumenty:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Volání metod centra z klienta je podporováno pouze při použití služby Azure SignalR ve výchozím režimu. Další informace najdete v tématu Nejčastější dotazy (úložiště Azure–signalr GitHub).
Metoda invoke
vrátí JavaScript Promise
. Vyřeší se Promise
návratovou hodnotou (pokud existuje), když metoda na serveru vrátí. Pokud metoda na serveru vyvolá chybu, Promise
je odmítnuta s chybovou zprávou. K řešení těchto případů použijte async
a await
nebo Promise
metody then
a catch
metody.
Klienti JavaScriptu mohou také volat veřejné metody v centrech prostřednictvím metody HubConnection
odeslání . invoke
Na rozdíl od metody metoda send
nečeká na odpověď ze serveru. Metoda send
vrátí JavaScript Promise
. Tato Promise
zpráva se vyřeší, když se zpráva odešle na server. Pokud dojde k chybě při odesílání zprávy, Promise
zpráva se odmítne s chybovou zprávou. K řešení těchto případů použijte async
a await
nebo Promise
metody then
a catch
metody.
Použití send
nečeká na přijetí zprávy serverem. V důsledku toho není možné ze serveru vracet data ani chyby.
Volání metod klienta z centra
Chcete-li přijímat zprávy z centra, definujte metodu pomocí metody on metoda HubConnection
.
- Název metody klienta JavaScriptu.
- Argumenty, které centrum předá metodě.
V následujícím příkladu je ReceiveMessage
název metody . Názvy argumentů jsou user
a message
:
connection.on("ReceiveMessage", (user, message) => {
const li = document.createElement("li");
li.textContent = `${user}: ${message}`;
document.getElementById("messageList").appendChild(li);
});
Předchozí kód se connection.on
spustí při volání kódu na straně serveru pomocí SendAsync metody:
using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs;
public class ChatHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
SignalR určuje, kterou metodu klienta se má volat podle názvu metody a argumentů definovaných v SendAsync
a connection.on
.
Osvědčeným postupem je volat metodu start na HubConnection
následující on
. Tím zajistíte, aby obslužné rutiny byly registrovány před přijetím všech zpráv.
Zpracování chyb a protokolování
Umožňuje console.error
vypsat chyby do konzoly prohlížeče, když se klient nemůže připojit nebo odeslat zprávu:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Nastavte trasování protokolu na straně klienta předáním protokolovacího nástroje a typu události, která se má protokolovat při vytváření připojení. Zprávy se protokolují se zadanou úrovní protokolu a vyšší. Dostupné úrovně protokolů jsou následující:
signalR.LogLevel.Error
: Chybové zprávy. ProtokolujeError
pouze zprávy.signalR.LogLevel.Warning
: Upozornění na potenciální chyby. ProtokolyWarning
aError
zprávy.signalR.LogLevel.Information
: Stavové zprávy bez chyb. ProtokolyInformation
aWarning
Error
zprávy.signalR.LogLevel.Trace
: Trasování zpráv. Zaznamená všechno, včetně dat přenášených mezi centrem a klientem.
Ke konfiguraci úrovně protokolu použijte metodu configureLogging na HubConnectionBuilder . Zprávy se protokolují do konzoly prohlížeče:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
Opětovné připojení klientů
Automatické opětovné připojení
Klienta JavaScriptu pro SignalR lze nakonfigurovat tak, aby se automaticky znovu připojil pomocí metody WithAutomaticReconnect v HubConnectionBuilder. Ve výchozím nastavení se automaticky nepřipojí.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Bez jakýchkoli parametrů nakonfiguruje WithAutomaticReconnect klienta tak, aby čekal 0, 2, 10 a 30 sekund před pokusem o opětovné připojení. Po čtyřech neúspěšných pokusech se přestane znovu připojovat.
Před zahájením jakýchkoli pokusů o opětovné připojení:HubConnection
- Přejde do
HubConnectionState.Reconnecting
stavu a aktivuje zpětnáonreconnecting
volání. - Nepřechází do
Disconnected
stavu a neaktivuje zpětnáonclose
volání jakoHubConnection
bez konfigurace automatického opětovného připojení.
Přístup k opětovnému připojení poskytuje příležitost:
- Upozornit uživatele, že připojení bylo ztraceno.
- Zakažte prvky uživatelského rozhraní.
connection.onreconnecting(error => {
console.assert(connection.state === signalR.HubConnectionState.Reconnecting);
document.getElementById("messageInput").disabled = true;
const li = document.createElement("li");
li.textContent = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageList").appendChild(li);
});
Pokud se klient úspěšně znovu připojí během prvních čtyř pokusů, HubConnection
přechody zpět do Connected
stavu a aktivují zpětná onreconnected
volání. To poskytuje možnost informovat uživatele, že připojení bylo znovu obnoveno.
Vzhledem k tomu, že připojení na serveru vypadá zcela nové, poskytuje onreconnected
se zpětná connectionId
volání.
Parametr onreconnected
zpětného connectionId
volání není definován, pokud HubConnection
je nakonfigurovaný tak, aby přeskočí vyjednávání.
connection.onreconnected(connectionId => {
console.assert(connection.state === signalR.HubConnectionState.Connected);
document.getElementById("messageInput").disabled = false;
const li = document.createElement("li");
li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`;
document.getElementById("messageList").appendChild(li);
});
withAutomaticReconnect
nenakonfiguruje HubConnection
opakování neúspěšných počátečních spuštění, takže chyby spuštění je potřeba zpracovat ručně:
async function start() {
try {
await connection.start();
console.assert(connection.state === signalR.HubConnectionState.Connected);
console.log("SignalR Connected.");
} catch (err) {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
console.log(err);
setTimeout(() => start(), 5000);
}
};
Pokud se klient během prvních čtyř pokusů úspěšně nepřipojí, HubConnection
přejde do Disconnected
stavu a aktivuje zpětná volání onkose . To poskytuje příležitost informovat uživatele:
- Připojení bylo trvale ztraceno.
- Zkuste aktualizovat stránku:
connection.onclose(error => {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
document.getElementById("messageInput").disabled = true;
const li = document.createElement("li");
li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the connection.`;
document.getElementById("messageList").appendChild(li);
});
Pokud chcete nakonfigurovat vlastní počet pokusů o opětovné připojení před odpojením nebo změnou časování opětovného připojení, withAutomaticReconnect
přijme pole čísel představující zpoždění v milisekundách, aby se čekalo před zahájením každého pokusu o opětovné připojení.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect([0, 0, 10000])
.build();
// .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior
Předchozí příklad nakonfiguruje HubConnection
pokus o opětovné připojení okamžitě po ztrátě připojení. Výchozí konfigurace také čeká nula sekund, než se pokusí znovu připojit.
Pokud první pokus o opětovné připojení selže, druhý pokus o opětovné připojení se spustí také okamžitě místo čekání 2 sekund pomocí výchozí konfigurace.
Pokud druhý pokus o opětovné připojení selže, spustí se třetí pokus o opětovné připojení za 10 sekund, což je stejné jako výchozí konfigurace.
Nakonfigurované časování opětovného připojení se liší od výchozího chování zastavením po selhání třetího pokusu o opětovné připojení místo pokusu o další pokus o opětovné připojení za dalších 30 sekund.
Pro větší kontrolu nad časováním a počtem automatických pokusů o withAutomaticReconnect
opětovné připojení přijímá objekt implementuje IRetryPolicy
rozhraní, který má jednu metodu s názvem nextRetryDelayInMilliseconds
.
nextRetryDelayInMilliseconds
přebírá jeden argument s typem RetryContext
. Má RetryContext
tři vlastnosti: previousRetryCount
a elapsedMilliseconds
retryReason
které jsou , number
number
a Error
v uvedeném pořadí. Před prvním opakovaným pokusem o připojení bude nula previousRetryCount
elapsedMilliseconds
a retryReason
chyba, která způsobila ztrátu připojení. Po každém neúspěšném pokusu o previousRetryCount
opakování se zvýší o jeden, elapsedMilliseconds
aktualizuje se tak, aby odrážel dobu strávenou opětovným připojením v milisekundách a retryReason
chyba, která způsobila poslední pokus o opětovné připojení k selhání.
nextRetryDelayInMilliseconds
musí vrátit číslo představující počet milisekund, které se mají počkat před dalším pokusem o opětovné připojení, nebo null
pokud HubConnection
by se mělo znovu připojit.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.elapsedMilliseconds < 60000) {
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
return Math.random() * 10000;
} else {
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
}
})
.build();
Případně můžete napsat kód, který klienta znovu připojí ručně, jak je znázorněno v následující části.
Ruční opětovné připojení
Následující kód ukazuje typický přístup k ručnímu opětovnému připojení:
- Vytvoří se funkce (v tomto případě
start
funkce) pro spuštění připojení. start
Volání funkce v obslužné rutiněonclose
události připojení.
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
Produkční implementace obvykle používají exponenciální zpětné vypnutí nebo opakují zadaný počet opakování.
Karta Spánku prohlížeče
Některé prohlížeče mají funkci zamrznutí tabulátoru nebo režimu spánku, která snižuje využití prostředků počítače pro neaktivní karty. To může způsobit SignalR zavření připojení a může vést k nežádoucímu uživatelskému prostředí. Prohlížeče používají heuristiku k zjištění, jestli se má karta umístit do režimu spánku, například:
- Přehrávání zvuku
- Podržení zámku webu
- Podržení
IndexedDB
zámku - Připojení k zařízení USB
- Zachytávání videa nebo zvuku
- Zrcadlení
- Zachycení okna nebo zobrazení
Heuristika prohlížeče se může v průběhu času měnit a může se mezi prohlížeči lišit. Projděte si matici podpory a zjistěte, jaká metoda je pro vaše scénáře nejvhodnější.
Aby se zabránilo umístění aplikace do režimu spánku, měla by aplikace aktivovat jednu z heuristik, které prohlížeč používá.
Následující příklad kódu ukazuje, jak pomocí webového zámku udržet kartu vzhůru a vyhnout se neočekávanému uzavření připojení.
var lockResolver;
if (navigator && navigator.locks && navigator.locks.request) {
const promise = new Promise((res) => {
lockResolver = res;
});
navigator.locks.request('unique_lock_name', { mode: "shared" }, () => {
return promise;
});
}
Pro předchozí příklad kódu:
- Webové zámky jsou experimentální. Podmíněná kontrola potvrzuje, že prohlížeč podporuje webové zámky.
- Překladač příslibů je uložený tak,
lockResolver
aby zámek mohl být uvolněn, když je přijatelná pro kartu do režimu spánku. - Při zavírání připojení se zámek uvolní voláním
lockResolver()
. Jakmile se zámek uvolní, karta může spát.
Další materiály
Autor: Rachel Appel
Klientská knihovna ASP.NET Core SignalR JavaScript umožňuje vývojářům volat kód centra na straně serveru.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
SignalR Instalace balíčku klienta
Klientská SignalR knihovna JavaScriptu se doručí jako balíček npm . Následující části popisují různé způsoby instalace klientské knihovny.
Instalace pomocí npm
Pro Visual Studio spusťte v kořenové složce následující příkazy z konzoly Správce balíčků. Pro Visual Studio Code spusťte z integrovaného terminálu následující příkazy.
npm init -y
npm install @microsoft/signalr
npm nainstaluje obsah balíčku do složky node_modules\@microsoft\signalr\dist\browser . Vytvořte novou složku s názvem signalr wwwroot\lib . signalr.js
Zkopírujte soubor do složky wwwroot\lib\signalr.
Odkazovat na javascriptového SignalR klienta v elementu <script>
. Příklad:
<script src="~/lib/signalr/signalr.js"></script>
Použití sítě pro doručování obsahu (CDN)
Chcete-li použít klientskou knihovnu bez předpokladu npm, odkazujte na kopii klientské knihovny hostované v CDN. Příklad:
<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.js"></script>
Klientská knihovna je k dispozici v následujících sítích CDN:
Instalace pomocí nástroje LibMan
Knihovnu LibMan lze použít k instalaci konkrétních souborů klientské knihovny z klientské knihovny hostované v CDN. Například do projektu přidejte pouze minifikovaný javascriptový soubor. Podrobnosti o tomto přístupu najdete v SignalR tématu Přidání klientské knihovny.
Připojení k centru
Následující kód vytvoří a spustí připojení. Název centra nerozlišuje velká a malá písmena:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
// Start the connection.
start();
Připojení mezi zdroji
Prohlížeče obvykle načítají připojení ze stejné domény jako požadovaná stránka. Existují však situace, kdy se vyžaduje připojení k jiné doméně.
Důležité
Kód klienta musí místo relativní adresy URL použít absolutní adresu URL. Změňte .withUrl("/chathub")
na .withUrl("https://myappurl/chathub")
.
Aby se zabránilo škodlivému webu ve čtení citlivých dat z jiného webu, jsou ve výchozím nastavení zakázaná připojení mezi zdroji. Pokud chcete povolit požadavek mezi zdroji, povolte ho Startup
ve třídě:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using SignalRChat.Hubs;
namespace SignalRChat
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddSignalR();
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.WithOrigins("https://example.com")
.AllowCredentials();
});
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapHub<ChatHub>("/chathub");
});
}
}
}
Metody centra volání z klienta
Klienti JavaScriptu volají veřejné metody v centrech prostřednictvím metody vyvolání HubConnection. Metoda invoke
přijímá:
- Název metody centra.
- Všechny argumenty definované v metodě centra.
V následujícím příkladu je název metody v centru .SendMessage
Druhý a třetí argument předaný pro invoke
mapování na metody user
centra a message
argumenty:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Poznámka:
Volání metod centra z klienta je podporováno pouze při použití služby Azure SignalR ve výchozím režimu. Další informace najdete v tématu Nejčastější dotazy (úložiště Azure–signalr GitHub).
Metoda invoke
vrátí JavaScript Promise
. Vyřeší se Promise
návratovou hodnotou (pokud existuje), když metoda na serveru vrátí. Pokud metoda na serveru vyvolá chybu, Promise
je odmítnuta s chybovou zprávou. K řešení těchto případů použijte async
a await
nebo Promise
metody then
a catch
metody.
Klienti JavaScriptu mohou také volat veřejné metody v centrech prostřednictvím metody HubConnection
odeslání . invoke
Na rozdíl od metody metoda send
nečeká na odpověď ze serveru. Metoda send
vrátí JavaScript Promise
. Tato Promise
zpráva se vyřeší, když se zpráva odešle na server. Pokud dojde k chybě při odesílání zprávy, Promise
zpráva se odmítne s chybovou zprávou. K řešení těchto případů použijte async
a await
nebo Promise
metody then
a catch
metody.
Poznámka:
Použití send
nečeká na přijetí zprávy serverem. V důsledku toho není možné ze serveru vracet data ani chyby.
Volání metod klienta z centra
Chcete-li přijímat zprávy z centra, definujte metodu pomocí metody on metoda HubConnection
.
- Název metody klienta JavaScriptu.
- Argumenty, které centrum předá metodě.
V následujícím příkladu je ReceiveMessage
název metody . Názvy argumentů jsou user
a message
:
connection.on("ReceiveMessage", (user, message) => {
const li = document.createElement("li");
li.textContent = `${user}: ${message}`;
document.getElementById("messageList").appendChild(li);
});
Předchozí kód se connection.on
spustí při volání kódu na straně serveru pomocí SendAsync metody:
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
SignalR určuje, kterou metodu klienta se má volat podle názvu metody a argumentů definovaných v SendAsync
a connection.on
.
Poznámka:
Osvědčeným postupem je volat metodu start na HubConnection
následující on
. Tím zajistíte, aby obslužné rutiny byly zaregistrovány před přijetím všech zpráv.
Zpracování chyb a protokolování
Používejte try
a catch
s async
metodou a await
nebo metodou catch
Promise
zpracování chyb na straně klienta. Slouží console.error
k výstupu chyb do konzoly prohlížeče:
try {
await connection.invoke("SendMessage", user, message);
} catch (err) {
console.error(err);
}
Nastavte trasování protokolu na straně klienta předáním protokolovacího nástroje a typu události, která se má protokolovat při vytváření připojení. Zprávy se protokolují se zadanou úrovní protokolu a vyšší. Dostupné úrovně protokolů jsou následující:
signalR.LogLevel.Error
: Chybové zprávy. ProtokolujeError
pouze zprávy.signalR.LogLevel.Warning
: Upozornění na potenciální chyby. ProtokolyWarning
aError
zprávy.signalR.LogLevel.Information
: Stavové zprávy bez chyb. ProtokolyInformation
aWarning
Error
zprávy.signalR.LogLevel.Trace
: Trasování zpráv. Zaznamená všechno, včetně dat přenášených mezi centrem a klientem.
Ke konfiguraci úrovně protokolu použijte metodu configureLogging na HubConnectionBuilder . Zprávy se protokolují do konzoly prohlížeče:
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.configureLogging(signalR.LogLevel.Information)
.build();
Opětovné připojení klientů
Automatické opětovné připojení
Klienta JavaScriptu pro SignalR lze nakonfigurovat tak, aby se automaticky znovu připojil pomocí withAutomaticReconnect
metody v HubConnectionBuilder. Ve výchozím nastavení se automaticky nepřipojí.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect()
.build();
Bez jakýchkoli parametrů nakonfiguruje klienta tak, withAutomaticReconnect()
aby čekal 0, 2, 10 a 30 sekund před pokusem o opětovné připojení a zastavil se po čtyřech neúspěšných pokusech.
Před zahájením jakýchkoli pokusů o HubConnection
opětovné připojení přejde do HubConnectionState.Reconnecting
stavu a aktivuje zpětná onreconnecting
volání místo přechodu na Disconnected
stav a aktivuje zpětná onclose
volání jako HubConnection
bez automatického opětovného připojení nakonfigurované. To poskytuje možnost upozornit uživatele, že připojení bylo ztraceno a zakázat prvky uživatelského rozhraní.
connection.onreconnecting(error => {
console.assert(connection.state === signalR.HubConnectionState.Reconnecting);
document.getElementById("messageInput").disabled = true;
const li = document.createElement("li");
li.textContent = `Connection lost due to error "${error}". Reconnecting.`;
document.getElementById("messageList").appendChild(li);
});
Pokud se klient úspěšně znovu připojí během prvních čtyř pokusů, HubConnection
přejde zpět do Connected
stavu a aktivuje zpětná onreconnected
volání. To poskytuje možnost informovat uživatele, že připojení bylo znovu obnoveno.
Vzhledem k tomu, že připojení na serveru vypadá zcela nové, bude zpětnému onreconnected
volání poskytováno novéconnectionId
.
Upozorňující
Parametr onreconnected
zpětného connectionId
volání nebude definován, pokud HubConnection
byl nakonfigurován tak, aby přeskočí vyjednávání.
connection.onreconnected(connectionId => {
console.assert(connection.state === signalR.HubConnectionState.Connected);
document.getElementById("messageInput").disabled = false;
const li = document.createElement("li");
li.textContent = `Connection reestablished. Connected with connectionId "${connectionId}".`;
document.getElementById("messageList").appendChild(li);
});
withAutomaticReconnect()
nenakonfiguruje HubConnection
opakování neúspěšných počátečních spuštění, takže chyby spuštění je potřeba zpracovat ručně:
async function start() {
try {
await connection.start();
console.assert(connection.state === signalR.HubConnectionState.Connected);
console.log("SignalR Connected.");
} catch (err) {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
console.log(err);
setTimeout(() => start(), 5000);
}
};
Pokud se klient během prvních čtyř pokusů úspěšně nepřipojí, HubConnection
přejde do Disconnected
stavu a aktivuje zpětná volání. To poskytuje příležitost informovat uživatele, že připojení bylo trvale ztraceno a doporučit aktualizaci stránky:
connection.onclose(error => {
console.assert(connection.state === signalR.HubConnectionState.Disconnected);
document.getElementById("messageInput").disabled = true;
const li = document.createElement("li");
li.textContent = `Connection closed due to error "${error}". Try refreshing this page to restart the connection.`;
document.getElementById("messageList").appendChild(li);
});
Pokud chcete nakonfigurovat vlastní počet pokusů o opětovné připojení před odpojením nebo změnou časování opětovného připojení, withAutomaticReconnect
přijme pole čísel představující zpoždění v milisekundách, aby se čekalo před zahájením každého pokusu o opětovné připojení.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect([0, 0, 10000])
.build();
// .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior
Předchozí příklad nakonfiguruje HubConnection
pokus o opětovné připojení okamžitě po ztrátě připojení. To platí i pro výchozí konfiguraci.
Pokud první pokus o opětovné připojení selže, druhý pokus o opětovné připojení se spustí také okamžitě místo čekání na 2 sekundy, jako by byl ve výchozí konfiguraci.
Pokud druhý pokus o opětovné připojení selže, třetí pokus o opětovné připojení se spustí za 10 sekund, což je znovu jako výchozí konfigurace.
Vlastní chování se pak znovu liší od výchozího chování zastavením po selhání třetího pokusu o opětovné připojení místo pokusu o další pokus o opětovné připojení za dalších 30 sekund, jako by to bylo ve výchozí konfiguraci.
Chcete-li ještě větší kontrolu nad časováním a počtem automatických pokusů o opětovné připojení, withAutomaticReconnect
přijímá objekt implementuje IRetryPolicy
rozhraní, který má jednu metodu s názvem nextRetryDelayInMilliseconds
.
nextRetryDelayInMilliseconds
přebírá jeden argument s typem RetryContext
. Má RetryContext
tři vlastnosti: previousRetryCount
a elapsedMilliseconds
retryReason
které jsou , number
number
a Error
v uvedeném pořadí. Před prvním opakovaným pokusem o připojení bude nula previousRetryCount
elapsedMilliseconds
a retryReason
chyba, která způsobila ztrátu připojení. Po každém neúspěšném pokusu o previousRetryCount
opakování se zvýší o jeden, elapsedMilliseconds
aktualizuje se tak, aby odrážel dobu strávenou opětovným připojením v milisekundách a retryReason
chyba, která způsobila poslední pokus o opětovné připojení k selhání.
nextRetryDelayInMilliseconds
musí vrátit číslo představující počet milisekund, které se mají počkat před dalším pokusem o opětovné připojení, nebo null
pokud HubConnection
by se mělo znovu připojit.
const connection = new signalR.HubConnectionBuilder()
.withUrl("/chathub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: retryContext => {
if (retryContext.elapsedMilliseconds < 60000) {
// If we've been reconnecting for less than 60 seconds so far,
// wait between 0 and 10 seconds before the next reconnect attempt.
return Math.random() * 10000;
} else {
// If we've been reconnecting for more than 60 seconds so far, stop reconnecting.
return null;
}
}
})
.build();
Případně můžete napsat kód, který klienta znovu připojí ručně, jak je znázorněno v tématu Ruční opětovné připojení.
Ruční opětovné připojení
Následující kód ukazuje typický přístup k ručnímu opětovnému připojení:
- Vytvoří se funkce (v tomto případě
start
funkce) pro spuštění připojení. start
Volání funkce v obslužné rutiněonclose
události připojení.
async function start() {
try {
await connection.start();
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
setTimeout(start, 5000);
}
};
connection.onclose(async () => {
await start();
});
Produkční implementace obvykle používají exponenciální zpětné vypnutí nebo opakují zadaný počet opakování.
Karta Spánku prohlížeče
Některé prohlížeče mají funkci zamrznutí tabulátoru nebo režimu spánku, která snižuje využití prostředků počítače pro neaktivní karty. To může způsobit SignalR zavření připojení a může vést k nežádoucímu uživatelskému prostředí. Prohlížeče používají heuristiku k zjištění, jestli se má karta umístit do režimu spánku, například:
- Přehrávání zvuku
- Podržení zámku webu
- Podržení
IndexedDB
zámku - Připojení k zařízení USB
- Zachytávání videa nebo zvuku
- Zrcadlení
- Zachycení okna nebo zobrazení
Poznámka:
Tyto heuristiky se můžou v průběhu času měnit nebo se mezi prohlížeči liší. Zkontrolujte matici podpory a zjistěte, jakou metodu je pro vaše scénáře nejvhodnější.
Aby se zabránilo umístění aplikace do režimu spánku, měla by aplikace aktivovat jednu z heuristik, které prohlížeč používá.
Následující příklad kódu ukazuje, jak pomocí webového zámku udržet kartu vzhůru a vyhnout se neočekávanému uzavření připojení.
var lockResolver;
if (navigator && navigator.locks && navigator.locks.request) {
const promise = new Promise((res) => {
lockResolver = res;
});
navigator.locks.request('unique_lock_name', { mode: "shared" }, () => {
return promise;
});
}
Pro předchozí příklad kódu:
- Webové zámky jsou experimentální. Podmíněná kontrola potvrzuje, že prohlížeč podporuje webové zámky.
- Překladač příslibů (
lockResolver
) je uložený tak, aby se zámek mohl uvolnit, až bude karta přijatelná pro režim spánku. - Při zavírání připojení se zámek uvolní voláním
lockResolver()
. Jakmile se zámek uvolní, karta může spát.