Dela via


ASP.NET Core SignalR JavaScript-klient

Med klientbiblioteket ASP.NET Core SignalR JavaScript kan utvecklare anropa hubbkod på serversidan SignalR .

Installera SignalR-klientpaketet

JavaScript-klientbiblioteket SignalR levereras som ett npm-paket . I följande avsnitt beskrivs olika sätt att installera klientbiblioteket.

Installera med npm

Kör följande kommandon från Package Manager-konsolen:

npm init -y
npm install @microsoft/signalr

npm installerar paketinnehållet i mappen node_modules\@microsoft\signalr\dist\browser . Skapa mappen wwwroot/lib/signalr . signalr.js Kopiera filen till mappen wwwroot/lib/signalr.

Referera till JavaScript-klienten SignalR i -elementet <script> . Till exempel:

<script src="~/lib/signalr/signalr.js"></script>

Använda ett nätverk för innehållsleverans (CDN)

Om du vill använda klientbiblioteket utan krav på npm refererar du till en CDN-värdbaserad kopia av klientbiblioteket. Till exempel:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/6.0.1/signalr.js"></script>

I föregående markering anges version 6.0.1. Välj något av följande CDN:er för att hämta den senaste klientbiblioteksversionen:

Installera med LibMan

LibMan kan användas för att installera specifika klientbiblioteksfilerna från klientbiblioteket som är värd via CDN. Du kan till exempel bara lägga till den minifierade JavaScript-filen i projektet. Mer information om den metoden finns i SignalR Lägg till klientbiblioteket.

Ansluta till en hubb

Följande kod skapar och startar en anslutning. Hubbens namn är skiftlägesokänsligt:

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();

Ursprungsöverskridande anslutningar (CORS)

Vanligtvis läser webbläsare in anslutningar från samma domän som den begärda sidan. Det finns dock tillfällen då en anslutning till en annan domän krävs.

När du gör begäranden mellan domänermåste klientkoden använda en absolut URL i stället för en relativ URL. För begäranden mellan domäner ändrar du .withUrl("/chathub") till .withUrl("https://{App domain name}/chathub").

För att förhindra att en skadlig webbplats läser känsliga data från en annan plats inaktiveras anslutningar mellan ursprung som standard. Om du vill tillåta en begäran om korsande ursprung aktiverar du 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 måste anropas innan du anropar MapHub.

Anropa hubbmetoder från klienten

JavaScript-klienter anropar offentliga metoder på hubbar via metoden invoke för HubConnection. Metoden invoke accepterar:

  • Namnet på hubbmetoden.
  • Alla argument som definierats i hubbmetoden.

I följande markerade kod är SendMessagemetodnamnet på hubben . De andra och tredje argumenten som skickas till invoke mappar till hubbmetodens argument user och message.

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Anropa hubbmetoder från en klient stöds bara när du använder Azure-tjänsten SignalR i standardläge . Mer information finns i Vanliga frågor och svar (GitHub-lagringsplats för azure-signalr).

Metoden invoke returnerar ett JavaScript Promise. Promise Löses med returvärdet (om det finns) när metoden på servern returneras. Om metoden på servern utlöser ett fel Promise avvisas den med felmeddelandet. Använd async och await eller Promise-metoderna then och catch för att hantera dessa fall.

JavaScript-klienter kan också anropa offentliga metoder på hubbar via send-metoden för HubConnection. invoke Till skillnad från metoden send väntar metoden inte på ett svar från servern. Metoden send returnerar ett JavaScript Promise. Promise Löses när meddelandet har skickats till servern. Om det uppstår ett fel när meddelandet Promise skickas avvisas meddelandet med felmeddelandet. Använd async och await eller Promise-metoderna then och catch för att hantera dessa fall.

Att använda send innebär inte att man väntar tills servern har tagit emot meddelandet. Därför går det inte att returnera data eller fel från servern.

Anropa klientmetoder från hubben

Om du vill ta emot meddelanden från hubben definierar du en metod med hjälp av on-metoden för HubConnection.

  • Namnet på JavaScript-klientmetoden.
  • Argument som hubben skickar till metoden.

I följande exempel är ReceiveMessagemetodnamnet . Argumentnamnen är user och message:

connection.on("ReceiveMessage", (user, message) => {
    const li = document.createElement("li");
    li.textContent = `${user}: ${message}`;
    document.getElementById("messageList").appendChild(li);
});

Föregående kod i connection.on körs när kod på serversidan anropar den med hjälp av metoden SendAsync:

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 avgör vilken klientmetod som ska anropas genom att matcha metodnamnet och argumenten som definierats i SendAsync och connection.on.

Bästa praxis är att anropa startmetodenHubConnection efter on. Detta säkerställer att hanterarna registreras innan några meddelanden tas emot.

Felhantering och loggning

Använd console.error för att mata ut fel till webbläsarens konsol när klienten inte kan ansluta eller skicka ett meddelande:

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Konfigurera loggspårning på klientsidan genom att skicka en loggare och en typ av händelse för att logga när anslutningen upprättas. Meddelanden loggas med den angivna loggnivån och högre. Tillgängliga loggnivåer är följande:

  • signalR.LogLevel.Error:Felmeddelanden. Loggar endast meddelanden Error.
  • signalR.LogLevel.Warning: Varningsmeddelanden om potentiella fel. WarningLoggar och Error meddelanden.
  • signalR.LogLevel.Information: Statusmeddelanden utan fel. Loggar Information, Warning och Error meddelanden.
  • signalR.LogLevel.Trace: Spårningsmeddelanden. Loggar allt, inklusive data som transporteras mellan hubben och klienten.

Använd metoden configureLoggingHubConnectionBuilder för att konfigurera loggnivån. Meddelanden loggas till webbläsarkonsolen:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

Återansluta klienter

Återanslut automatiskt

JavaScript-klienten för SignalR kan konfigureras att automatiskt återansluta med metoden WithAutomaticReconnectHubConnectionBuilder. Den återansluts inte automatiskt som standard.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect()
    .build();

Utan några parametrar konfigurerar WithAutomaticReconnect klienten att vänta 0, 2, 10 respektive 30 sekunder innan varje återanslutningsförsök provas. Efter fyra misslyckade försök slutar den att försöka återansluta.

Innan du påbörjar några återanslutningsförsök, bör du:HubConnection

  • Övergår till tillståndet HubConnectionState.Reconnecting och aktiverar dess onreconnecting återanrop.
  • Övergår inte till tillståndet Disconnected och utlöser dess onclose-återanrop som en HubConnection där automatisk återanslutning inte är konfigurerad.

Metoden för återanslutning ger en möjlighet att:

  • Varna användarna om att anslutningen har gått förlorad.
  • Inaktivera gränssnittselement.
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);
});

Om klienten återansluter inom de första fyra försöken, övergår HubConnection tillbaka till Connected läge och utlöser sina onreconnected återanrop. Detta ger en möjlighet att informera användarna om att anslutningen har återupprättats.

Eftersom anslutningen ser helt ny ut för servern tillhandahålls en ny connectionId till återanropet onreconnected .

Återanropets onreconnectedconnectionId parameter är odefinierad om den HubConnection är konfigurerad för att hoppa över förhandling.

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 kommer inte att konfigurera HubConnection för att försöka igen vid initiala startfel, så startfel måste hanteras manuellt:

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);
    }
};

Om klienten inte återansluter inom de första fyra försöken HubConnection övergår den till Disconnected tillståndet och utlöser dess inkl. återanrop. Detta ger en möjlighet att informera användarna:

  • Anslutningen har förlorats permanent.
  • Prova att uppdatera sidan:
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);
});

För att konfigurera ett anpassat antal återanslutningsförsök innan du kopplar från eller ändrar återanslutningstidpunkten accepterar withAutomaticReconnect en matris med tal som representerar fördröjningen i millisekunder att vänta innan varje återanslutningsförsök startas.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect([0, 0, 10000])
    .build();

    // .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

I föregående exempel konfigureras HubConnection för att börja försöka återansluta omedelbart efter att anslutningen har gått förlorad. Standardkonfigurationen väntar också noll sekunder på att försöka ansluta igen.

Om det första återanslutningsförsöket misslyckas startar det andra återanslutningsförsöket också omedelbart i stället för att vänta 2 sekunder med standardkonfigurationen.

Om det andra återanslutningsförsöket misslyckas startar det tredje återanslutningsförsöket på 10 sekunder, vilket är samma som standardkonfigurationen.

Den konfigurerade återanslutningstidpunkten skiljer sig från standardbeteendet genom att stoppa efter det tredje återanslutningsförsöksfelet i stället för att försöka göra ytterligare ett återanslutningsförsök på ytterligare 30 sekunder.

Om du vill ha mer kontroll över tidpunkten och antalet automatiska återanslutningsförsök withAutomaticReconnect godkänner du ett objekt som implementerar IRetryPolicy gränssnittet, som har en enda metod med namnet nextRetryDelayInMilliseconds.

nextRetryDelayInMilliseconds tar ett argument med typen RetryContext. RetryContext Har tre egenskaper: previousRetryCount, elapsedMilliseconds och retryReason som är en number, en numberError respektive. Före det första återanslutningsförsöket är båda previousRetryCount och elapsedMilliseconds noll, och retryReason kommer att vara felet som gjorde att anslutningen gick förlorad. Efter varje misslyckat återförsök previousRetryCount ökas med ett, elapsedMilliseconds uppdateras för att återspegla den tid som lagts på att återansluta hittills i millisekunder, och retryReason kommer att vara felet som orsakade att det senaste återanslutningsförsöket misslyckades.

nextRetryDelayInMilliseconds måste returnera antingen ett tal som representerar antalet millisekunder som ska vänta innan nästa återanslutningsförsök eller null om HubConnection ska sluta ansluta igen.

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();

Du kan också skriva kod som återansluter klienten manuellt, vilket visas i följande avsnitt.

Återanslut manuellt

Följande kod visar en typisk manuell återanslutningsmetod:

  1. En funktion (i det här fallet start funktionen) skapas för att starta anslutningen.
  2. start Anropa funktionen i anslutningens onclose händelsehanterare.
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

connection.onclose(async () => {
    await start();
});

Produktionsimplementeringar använder vanligtvis en exponentiell tillbakagång eller försöker igen ett förutbestämt antal gånger.

Webbläsarens vilolägesflik

Vissa webbläsare har en flikfrysning eller vilofunktion för att minska datorresursanvändningen för inaktiva flikar. Detta kan leda SignalR till att anslutningar stängs och kan resultera i en oönskad användarupplevelse. Webbläsare använder heuristik för att ta reda på om en flik ska försättas i viloläge, till exempel:

  • Spela upp ljud
  • Hålla ett webblås
  • Att hålla ett IndexedDB lås
  • Anslutas till en USB-enhet
  • Spela in video eller ljud
  • Speglas
  • Avbilda ett fönster eller en bildskärm

Webbläsarens heuristik kan ändras över tid och kan skilja sig mellan webbläsare. Kontrollera supportmatrisen och ta reda på vilken metod som fungerar bäst för dina scenarier.

För att undvika att försätta en app i viloläge bör appen utlösa en av de heuristiker som webbläsaren använder.

Följande kodexempel visar hur du använder en Web Lock för att hålla en flik aktiv och undvika en oväntad avstängning av anslutningen.

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;
    });
}

För föregående kodexempel:

  • Webblås är experimentella. Den villkorliga kontrollen bekräftar att webbläsaren stöder webblås.
  • Promise Resolver, lockResolver, lagras så att låset kan frigöras när fliken kan sättas i viloläge.
  • När anslutningen stängs frigörs låset genom att anropa lockResolver(). När låset släpps tillåts fliken att vila.

Ytterligare resurser

Av Rachel Appel

Med klientbiblioteket ASP.NET Core SignalR JavaScript kan utvecklare anropa hubbkod på serversidan.

Visa eller ladda ned exempelkod (hur du laddar ned)

Installera SignalR-klientpaketet

JavaScript-klientbiblioteket SignalR levereras som ett npm-paket . I följande avsnitt beskrivs olika sätt att installera klientbiblioteket.

Installera med npm

För Visual Studio kör du följande kommandon från Package Manager Console i rotmappen. För Visual Studio Code kör du följande kommandon från den integrerade terminalen.

npm init -y
npm install @microsoft/signalr

npm installerar paketinnehållet i mappen node_modules\@microsoft\signalr\dist\browser . Skapa en ny mapp med namnet signalr under mappen wwwroot\lib . signalr.js Kopiera filen till mappen wwwroot\lib\signalr.

Referera till JavaScript-klienten SignalR i -elementet <script> . Till exempel:

<script src="~/lib/signalr/signalr.js"></script>

Använda ett nätverk för innehållsleverans (CDN)

Om du vill använda klientbiblioteket utan krav på npm refererar du till en CDN-värdbaserad kopia av klientbiblioteket. Till exempel:

<script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.7/signalr.js"></script>

Klientbiblioteket är tillgängligt på följande CDN:er:

Installera med LibMan

LibMan kan användas för att installera specifika klientbiblioteksfilerna från klientbiblioteket som är värd via CDN. Du kan till exempel bara lägga till den minifierade JavaScript-filen i projektet. Mer information om den metoden finns i SignalR Lägg till klientbiblioteket.

Ansluta till en hubb

Följande kod skapar och startar en anslutning. Hubbens namn är skiftlägesokänsligt:

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();

Anslutningar mellan ursprung

Vanligtvis läser webbläsare in anslutningar från samma domän som den begärda sidan. Det finns dock tillfällen då en anslutning till en annan domän krävs.

Important

Klientkoden måste använda en absolut URL i stället för en relativ URL. Ändra .withUrl("/chathub") till .withUrl("https://myappurl/chathub").

För att förhindra att en skadlig webbplats läser känsliga data från en annan plats inaktiveras anslutningar mellan ursprung som standard. Om du vill tillåta en begäran om korsande ursprung aktiverar du den i Startup klassen:

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");
            });
        }
    }
}

Anropa hubbmetoder från klienten

JavaScript-klienter anropar offentliga metoder på hubbar via metoden invoke för HubConnection. Metoden invoke accepterar:

  • Namnet på hubbmetoden.
  • Alla argument som definierats i hubbmetoden.

I följande exempel är SendMessagemetodnamnet på hubben . De andra och tredje argumenten som skickas till invoke mappar till hubbmetodens argument user och message.

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Note

Anrop av hubbmetoder från en klient stöds endast när man använder Azure SignalR-tjänsten i standardläge för. Mer information finns i Vanliga frågor och svar (GitHub-lagringsplats för azure-signalr).

Metoden invoke returnerar ett JavaScript Promise. Promise Löses med returvärdet (om det finns) när metoden på servern returneras. Om metoden på servern utlöser ett fel Promise avvisas den med felmeddelandet. Använd async och await eller Promise-metoderna then och catch för att hantera dessa fall.

JavaScript-klienter kan också anropa offentliga metoder på hubbar via send-metoden för HubConnection. invoke Till skillnad från metoden send väntar metoden inte på ett svar från servern. Metoden send returnerar ett JavaScript Promise. Promise Löses när meddelandet har skickats till servern. Om det uppstår ett fel när meddelandet Promise skickas avvisas meddelandet med felmeddelandet. Använd async och await eller Promise-metoderna then och catch för att hantera dessa fall.

Note

Att använda send väntar inte tills servern har tagit emot meddelandet. Därför går det inte att returnera data eller fel från servern.

Anropa klientmetoder från hubben

Om du vill ta emot meddelanden från hubben definierar du en metod med hjälp av on-metoden för HubConnection.

  • Namnet på JavaScript-klientmetoden.
  • Argument som hubben skickar till metoden.

I följande exempel är ReceiveMessagemetodnamnet . Argumentnamnen är user och message:

connection.on("ReceiveMessage", (user, message) => {
    const li = document.createElement("li");
    li.textContent = `${user}: ${message}`;
    document.getElementById("messageList").appendChild(li);
});

Föregående kod i connection.on körs när kod på serversidan anropar den med hjälp av metoden SendAsync:

public async Task SendMessage(string user, string message)
{
    await Clients.All.SendAsync("ReceiveMessage", user, message);
}

SignalR avgör vilken klientmetod som ska anropas genom att matcha metodnamnet och argumenten som definierats i SendAsync och connection.on.

Note

Vi rekommenderar att du anropar startmetodenHubConnection efter on. Detta säkerställer att dina hanterare registreras innan några meddelanden tas emot.

Felhantering och loggning

Använd try och catch med async och await eller Promise- catch metoden för att hantera fel på klientsidan. Använd console.error för att mata ut fel till webbläsarens konsol:

try {
    await connection.invoke("SendMessage", user, message);
} catch (err) {
    console.error(err);
}

Konfigurera loggspårning på klientsidan genom att skicka en loggare och en typ av händelse för att logga när anslutningen upprättas. Meddelanden loggas med den angivna loggnivån och högre. Tillgängliga loggnivåer är följande:

  • signalR.LogLevel.Error:Felmeddelanden. Loggar endast meddelanden Error.
  • signalR.LogLevel.Warning: Varningsmeddelanden om potentiella fel. WarningLoggar och Error meddelanden.
  • signalR.LogLevel.Information: Statusmeddelanden utan fel. Loggar Information, Warning och Error meddelanden.
  • signalR.LogLevel.Trace: Spårningsmeddelanden. Loggar allt, inklusive data som transporteras mellan hubben och klienten.

Använd metoden configureLoggingHubConnectionBuilder för att konfigurera loggnivån. Meddelanden loggas till webbläsarkonsolen:

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .configureLogging(signalR.LogLevel.Information)
    .build();

Återansluta klienter

Återanslut automatiskt

JavaScript-klienten för SignalR kan konfigureras att automatiskt återansluta med hjälp av withAutomaticReconnect-metoden på HubConnectionBuilder. Den återansluts inte automatiskt som standard.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect()
    .build();

Utan några parametrar withAutomaticReconnect() konfigurerar klienten att vänta 0, 2, 10 respektive 30 sekunder innan varje återanslutningsförsök provas och stoppas efter fyra misslyckade försök.

Innan några återanslutningsförsök påbörjas, kommer HubConnection att övergå till HubConnectionState.Reconnecting-tillståndet och utlösa sina onreconnecting-återanrop, istället för att övergå till Disconnected-tillståndet och utlösa sina onclose-återanrop som en HubConnection utan att automatisk återanslutning är konfigurerad. Detta ger en möjlighet att varna användarna om att anslutningen har gått förlorad och att inaktivera gränssnittselement.

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);
});

Om klienten framgångsrikt återansluter inom de första fyra försöken, kommer HubConnection att övergå tillbaka till Connected-tillståndet och utlösa dess onreconnected-återanrop. Detta ger en möjlighet att informera användarna om att anslutningen har återupprättats.

Eftersom anslutningen verkar helt ny för servern kommer en ny connectionId att tillhandahållas till onreconnected-callback-funktionen.

Warning

Återanropets onreconnectedconnectionId parameter kommer att vara odefinierad om den HubConnection har konfigurerats för att hoppa över förhandling.

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() kommer inte att konfigurera HubConnection för att försöka igen vid initiala startfel, så startfel måste hanteras manuellt:

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);
    }
};

Om klienten inte återansluter inom de första fyra försöken HubConnection övergår den till Disconnected tillståndet och utlöser dess inkl. återanrop. Detta ger en möjlighet att informera användarna om att anslutningen har förlorats permanent och rekommenderar att du uppdaterar sidan:

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);
});

För att konfigurera ett anpassat antal återanslutningsförsök innan du kopplar från eller ändrar återanslutningstidpunkten accepterar withAutomaticReconnect en matris med tal som representerar fördröjningen i millisekunder att vänta innan varje återanslutningsförsök startas.

const connection = new signalR.HubConnectionBuilder()
    .withUrl("/chathub")
    .withAutomaticReconnect([0, 0, 10000])
    .build();

    // .withAutomaticReconnect([0, 2000, 10000, 30000]) yields the default behavior

I föregående exempel konfigureras HubConnection för att börja försöka återansluta omedelbart efter att anslutningen har gått förlorad. Detta gäller även för standardkonfigurationen.

Om det första återanslutningsförsöket misslyckas startar även det andra återanslutningsförsöket omedelbart i stället för att vänta 2 sekunder som i standardkonfigurationen.

Om det andra återanslutningsförsöket misslyckas startar det tredje återanslutningsförsöket om 10 sekunder, vilket återigen liknar standardkonfigurationen.

Det anpassade beteendet avviker sedan igen från standardbeteendet genom att stoppa efter det tredje återanslutningsförsöksfelet i stället för att försöka göra ytterligare ett återanslutningsförsök på ytterligare 30 sekunder som i standardkonfigurationen.

Om du vill ha ännu mer kontroll över tidpunkten och antalet automatiska återanslutningsförsök withAutomaticReconnect godkänner du ett objekt som implementerar IRetryPolicy gränssnittet, som har en enda metod med namnet nextRetryDelayInMilliseconds.

nextRetryDelayInMilliseconds tar ett argument med typen RetryContext. RetryContext Har tre egenskaper: previousRetryCount, elapsedMilliseconds och retryReason som är en number, en numberError respektive. Före det första återanslutningsförsöket är båda previousRetryCount och elapsedMilliseconds noll, och retryReason kommer att vara felet som gjorde att anslutningen gick förlorad. Efter varje misslyckat återförsök previousRetryCount ökas med ett, elapsedMilliseconds uppdateras för att återspegla den tid som lagts på att återansluta hittills i millisekunder, och retryReason kommer att vara felet som orsakade att det senaste återanslutningsförsöket misslyckades.

nextRetryDelayInMilliseconds måste returnera antingen ett tal som representerar antalet millisekunder som ska vänta innan nästa återanslutningsförsök eller null om HubConnection ska sluta ansluta igen.

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();

Du kan också skriva kod som återansluter klienten manuellt, vilket visas i Återanslut manuellt.

Återanslut manuellt

Följande kod visar en typisk manuell återanslutningsmetod:

  1. En funktion (i det här fallet start funktionen) skapas för att starta anslutningen.
  2. start Anropa funktionen i anslutningens onclose händelsehanterare.
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

connection.onclose(async () => {
    await start();
});

Produktionsimplementeringar använder vanligtvis en exponentiell tillbakagång eller försöker igen ett förutbestämt antal gånger.

Webbläsarens vilolägesflik

Vissa webbläsare har en flikfrysning eller vilofunktion för att minska datorresursanvändningen för inaktiva flikar. Detta kan leda SignalR till att anslutningar stängs och kan resultera i en oönskad användarupplevelse. Webbläsare använder heuristik för att ta reda på om en flik ska försättas i viloläge, till exempel:

  • Spela upp ljud
  • Hålla ett webblås
  • Att hålla ett IndexedDB lås
  • Anslutas till en USB-enhet
  • Spela in video eller ljud
  • Speglas
  • Avbilda ett fönster eller en bildskärm

Note

Dessa heuristiker kan ändras över tid eller skilja sig mellan webbläsare. Kontrollera supportmatrisen och ta reda på vilken metod som fungerar bäst för dina scenarier.

För att undvika att försätta en app i viloläge bör appen utlösa en av de heuristiker som webbläsaren använder.

Följande kodexempel visar hur du använder en Web Lock för att hålla en flik aktiv och undvika en oväntad avstängning av anslutningen.

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;
    });
}

För föregående kodexempel:

  • Webblås är experimentella. Den villkorliga kontrollen bekräftar att webbläsaren stöder webblås.
  • Promise Resolver (lockResolver) lagras så att låset kan låsas upp när det är acceptabelt att fliken försätts i sovläge.
  • När anslutningen stängs frigörs låset genom att anropa lockResolver(). När låset släpps tillåts fliken att vila.

Ytterligare resurser