Megosztás a következőn keresztül:


ASP.NET Core SignalR JavaScript-ügyfél

A ASP.NET Core SignalR JavaScript-ügyfélkódtár lehetővé teszi a fejlesztők számára a kiszolgálóoldali SignalR központi kód meghívását.

Az SignalR ügyfélcsomag telepítése

A SignalR JavaScript-ügyfélkódtár npm-csomagként lesz kézbesítve. Az alábbi szakaszok az ügyfélkódtár telepítésének különböző módjait ismertetik.

Telepítés npm használatával

Futtassa a következő parancsokat a Package Manager-konzolon:

npm init -y
npm install @microsoft/signalr

Az npm telepíti a csomag tartalmát a node_modules\@microsoft\signalr\dist\browser mappába. Hozza létre a wwwroot/lib/signalr mappát. Másolja a fájlt a signalr.jswwwroot/lib/signalr mappába.

Hivatkozzon a SignalR JavaScript-klienst az <script> elemben. Például:

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

Tartalomkézbesítési hálózat (CDN) használata

Ha az ügyfélkódtárat az npm előfeltétele nélkül szeretné használni, hivatkozzon az ügyfélkódtár CDN által üzemeltetett példányára. Például:

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

Az előző jelölésben a 6.0.1-es verzió van megadva. Az ügyfélkódtár legújabb verziójának beszerzéséhez válasszon az alábbi CDN-k közül:

Telepítés a LibManrel

A LibMan a CDN-en tárolt ügyfél-oldali könyvtár adott fájljainak telepítésére használható. Például csak az összetömörített JavaScript fájlt adja hozzá a projekthez. Erről a megközelítésről további információt az SignalR ügyfélkódtár hozzáadása című témakörben talál.

Csatlakozás központhoz

Az alábbi kód létrehoz és elindít egy kapcsolatot. A központ neve nem érzékeny a kis- és nagybetűkre.

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

Forrásközi kapcsolatok (CORS)

A böngészők általában a kért oldallal megegyező tartományból töltik be a kapcsolatokat. Vannak azonban olyan esetek, amikor egy másik tartományhoz való csatlakozásra van szükség.

Tartományközi kérések esetén az ügyfélkódnak relatív URL-cím helyett abszolút URL-címet kell használnia. Tartományközi kérések esetén cserélje a .withUrl("/chathub")-t .withUrl("https://{App domain name}/chathub")-re.

Ha meg szeretné akadályozni, hogy egy rosszindulatú webhely bizalmas adatokat olvasson egy másik helyről, a rendszer alapértelmezés szerint letiltja a többhelyes kapcsolatokat . A forrásközi kérés engedélyezéséhez engedélyezze a CORS-t:

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 hívás előtt MapHubmeg kell hívni.

A hívásközpont metódusai az ügyféltől

A JavaScript-ügyfelek nyilvános metódusokat hívnak meg a hubokon a HubConnectionmeghívási módszerével. A invoke metódus a következőt fogadja el:

  • A hub módszer neve.
  • A hub metódusban definiált argumentumok.

Az alábbi kiemelt kódban a következő a hub metódusának neve: SendMessage. A második és a harmadik argumentum megegyezik a invoke a hub metódus user és message argumentumaival.

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

A központi metódusok ügyfélről való meghívása csak akkor támogatott, ha az Azure SignalR Service-t alapértelmezett módban használja. További információ: Gyakori kérdések (azure-signalr GitHub-adattár).

A invoke metódus Egy JavaScriptet Promisead vissza. A Promise a visszatérési értékkel (ha van ilyen) kerül feloldásra, amikor a kiszolgáló metódus visszatér. Ha a kiszolgálón lévő metódus hibát jelez, a Promise rendszer a hibaüzenettel elutasítja a metódust. Az ilyen esetek kezelésére használhatja async és a awaitPromise valamint then metódusokat.

A JavaScript-ügyfelek nyilvános metódusokat is meghívhatnak a hubokon a küldésiHubConnectionmetóduson keresztül. A invoke metódustól eltérően a send metódus nem várja meg a kiszolgáló válaszát. A send metódus Egy JavaScriptet Promisead vissza. A Promise probléma akkor szűnik meg, ha az üzenet el lett küldve a kiszolgálónak. Ha hibaüzenet jelenik meg az üzenet küldésekor, a Promise rendszer a hibaüzenettel együtt elutasítja az üzenetet. Az ilyen esetek kezelésére használhatja async és a awaitPromise valamint then metódusokat.

Használva sendnem vár, amíg a kiszolgáló megkapja az üzenetet. Következésképpen nem lehet adatokat vagy hibákat visszaadni a kiszolgálóról.

Az ügyfél metódusokat a hubról hívja

Ha üzeneteket szeretne fogadni a központból, definiáljon egy metódust az on metódussal a HubConnection.

  • A JavaScript-ügyfélmetódus neve.
  • A hub által a metódusnak megadott argumentumok.

Az alábbi példában a metódus neve .ReceiveMessage Az argumentumnevek user és message:

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

Az előző kód connection.on akkor fut le, amikor a kiszolgálóoldali kód meghívja azt a SendAsync metódus használatával:

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 meghatározza, hogy melyik kliens metódust kell meghívni a metódus nevének és argumentumainak SendAsync és connection.on egyeztetésével.

Legjobb gyakorlat a start metódus meghívása a HubConnection utánon. Ezzel biztosítja, hogy a kezelők regisztrálva legyenek az üzenetek fogadása előtt.

Hibakezelés és naplózás

Használja a console.error-t, hogy hibákat írjon ki a böngésző konzoljára, amikor az ügyfél nem tud csatlakozni vagy üzenetet küldeni.

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

Állítsa be az ügyféloldali naplókövetést úgy, hogy átad egy naplózót és egy eseménytípust a naplózáshoz a kapcsolat létrehozásakor. Az üzenetek a megadott naplószinttel illetve afeletti naplószintekkel kerülnek naplózásra. Az elérhető naplószintek a következők:

  • signalR.LogLevel.Error:Hibaüzenetek. Csak az üzeneteket naplózza Error .
  • signalR.LogLevel.Warning: Figyelmeztető üzenetek a lehetséges hibákról. Naplóz Warning, és Error üzeneteket.
  • signalR.LogLevel.Information: Állapotüzenetek hibák nélkül. Naplók Information, Warning és Error üzenetek.
  • signalR.LogLevel.Trace: Nyomkövetési üzenetek. Mindent naplóz, beleértve a központ és az ügyfél között szállított adatokat is.

A naplószint konfigurálásához használja a HubConnectionBuilderconfigureLogging metódusát. A rendszer naplózza az üzeneteket a böngészőkonzolon:

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

Ügyfelek újracsatlakoztatása

Automatikus újracsatlakozás

A SignalR JavaScript-ügyfél konfigurálható úgy, hogy a HubConnectionBuilder objektum WithAutomaticReconnect metódusával automatikusan újracsatlakozzon. Alapértelmezés szerint nem fog automatikusan újracsatlakozni.

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

Paraméterek nélkül a WithAutomaticReconnect úgy konfigurálja az ügyfelet, hogy 0, 2, 10 és 30 másodpercet várjon az egyes újracsatlakozási kísérletek kipróbálása előtt. Négy sikertelen kísérlet után nem próbál újracsatlakozni.

Az újracsatlakozási kísérletek megkezdése előtt a HubConnection következő:

  • Áttér az HubConnectionState.Reconnecting állapotra, és aktiválja a onreconnecting visszahívásokat.
  • Nem vált át az Disconnected állapotra, és nem aktiválja onclose a visszahívásokat, például automatikus HubConnection újracsatlakozás konfigurálása nélkül.

Az újracsatlakozási módszer lehetőséget nyújt a következő lehetőségekre:

  • Figyelmeztetheti a felhasználókat, hogy a kapcsolat megszakadt.
  • Felhasználói felület elemeinek letiltása.
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);
});

Ha az ügyfél sikeresen újracsatlakozik a első négy próbálkozáson belül, a HubConnection visszatér a Connected állapotba, és meghívja a onreconnected visszahívási függvényeit. Ez lehetőséget biztosít arra, hogy tájékoztassa a felhasználókat a kapcsolat újbóli létrejöttéről.

Mivel a kapcsolat teljesen újnak tűnik a kiszolgálón, egy új connectionId kerül biztosításra a onreconnected visszahíváshoz.

A onreconnected visszahívás connectionIdparamétere nincs meghatározva , ha a HubConnectionegyeztetés kihagyására van konfigurálva.

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 nem konfigurálja a HubConnection kezdeti indítási hibák újrapróbálkozását, ezért az indítási hibákat manuálisan kell kezelni:

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

Ha az ügyfélnek az első négy kísérlet során nem sikerül újracsatlakoznia, az HubConnection átkerül a Disconnected állapotba, és meghívja az onclose visszahívásait. Ez lehetőséget biztosít a felhasználók tájékoztatására:

  • A kapcsolat végleg megszakadt.
  • Próbálja meg frissíteni a lapot:
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);
});

Ha egyéni számú újracsatlakozási kísérletet szeretne konfigurálni a kapcsolat bontása vagy módosítása előtt, withAutomaticReconnect fogadja el az ezredmásodperc késleltetését jelző számtömböt, hogy az egyes újracsatlakozási kísérletek megkezdése előtt várakozzon.

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

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

Az előző példa úgy konfigurálja a HubConnection kapcsolatot, hogy a kapcsolat megszakadása után azonnal megkísérlje az újracsatlakozást. Az alapértelmezett konfiguráció is nulla másodpercet vár az újracsatlakozás megkísérléséhez.

Ha az első újracsatlakozási kísérlet meghiúsul, a második újracsatlakozási kísérlet is azonnal elindul, ahelyett, hogy 2 másodpercet várnál az alapértelmezett konfiguráció használatával.

Ha a második újracsatlakozási kísérlet meghiúsul, a harmadik újracsatlakozási kísérlet 10 másodperc múlva indul el, amely megegyezik az alapértelmezett konfigurációval.

A konfigurált újracsatlakozás időzítése eltér az alapértelmezett viselkedéstől azáltal, hogy a harmadik újracsatlakozási kísérlet meghiúsulása után leáll, nem pedig újabb 30 másodpercen belül próbálkozik újracsatlakozási kísérlettel.

Az automatikus újracsatlakozási kísérletek időzítésének és számának extra szabályozásához a withAutomaticReconnect egy olyan objektumot fogad el, mely az IRetryPolicy interfészt implementálja és egyetlen nextRetryDelayInMilliseconds nevű metódusa van.

nextRetryDelayInMilliseconds egyetlen argumentumot vesz fel a típussal RetryContext. A RetryContext három tulajdonsága: previousRetryCount, elapsedMilliseconds és retryReason, amelyek a number, a number és a Error. Az első újracsatlakozási kísérlet előtt mind a previousRetryCount, mind a elapsedMilliseconds nulla lesz, és a retryReason lesz az a hiba, ami a kapcsolat elvesztését okozta. Minden sikertelen újrapróbálkozási kísérlet previousRetryCount után a rendszer egy-egy lépéssel növekszik, a rendszer úgy frissül, elapsedMilliseconds hogy az tükrözze az újracsatlakozással töltött időt ezredmásodpercben, és az retryReason a hiba lesz, amely az utolsó újracsatlakozási kísérlet meghiúsulását okozta.

nextRetryDelayInMilliseconds vagy egy számot kell visszaadnia, amely az újracsatlakozási kísérlet előtt várandó ezredmásodpercek számát jelöli, vagy null értékét, ha az HubConnection újracsatlakozást le kell állítani.

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

Másik lehetőségként olyan kód írható, amely manuálisan csatlakoztatja újra az ügyfelet az alábbi szakaszban bemutatott módon.

Manuális újracsatlakozás

Az alábbi kód egy tipikus manuális újracsatlakozási megközelítést mutat be:

  1. A kapcsolat elindításához létrejön egy függvény (ebben az esetben a start függvény).
  2. Hívja meg a start függvényt a kapcsolat eseménykezelőjében onclose .
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

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

Az éles implementációk általában exponenciális visszatartást használnak, vagy adott számú alkalommal újrapróbálkoznak.

Böngésző alvó fül

Egyes böngészők lapfagyasztási vagy alvó funkcióval rendelkeznek az inaktív lapok számítógép-erőforrás-használatának csökkentéséhez. Ez a kapcsolatok bezárását okozhatja SignalR , és nemkívánatos felhasználói élményt eredményezhet. A böngészők heurisztikus megoldásokkal derítik ki, hogy alvó állapotba kell-e helyezni egy lapot, például:

  • Hang lejátszása
  • Webes zárolás megtartása
  • IndexedDB Zárolás tartása
  • USB-eszközhöz való csatlakozás
  • Videó vagy hang rögzítése
  • Tükrözés
  • Ablak vagy kijelző rögzítése

A böngésző heurisztikus funkciói idővel változhatnak, és a böngészők között eltérhetnek. Ellenőrizze a támogatási mátrixot, és állapítsa meg, hogy melyik módszer működik a legjobban a forgatókönyvekhez.

Az alkalmazás alvó állapotba helyezésének elkerülése érdekében az alkalmazásnak aktiválnia kell a böngésző által használt heurisztika egyikét.

Az alábbi példakód bemutatja, hogyan használhat webzárat egy lap ébren tartásához és a váratlan kapcsolatlezárás elkerüléséhez.

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

Az előző példakód esetében:

  • A webzárak kísérleti jellegűek. A feltételes ellenőrzés megerősíti, hogy a böngésző támogatja a webzárolásokat.
  • Az ígéret megoldója, lockResolver, úgy van tárolva, hogy a zárolás akkor oldható fel, amikor megengedhető, hogy a lap alvó állapotba kerüljön.
  • A kapcsolat bezárásakor a zárolás hívással lockResolver()feloldódik. A zárolás feloldásakor a lap alvó állapotba kerül.

További erőforrások

Készítette: Rachel Appel

A ASP.NET Core SignalR JavaScript-ügyfélkódtár lehetővé teszi a fejlesztők számára a kiszolgálóoldali központi kód meghívását.

Mintakód megtekintése vagy letöltése (hogyan töltsd le)

Az SignalR ügyfélcsomag telepítése

A SignalR JavaScript-ügyfélkódtár npm-csomagként lesz kézbesítve. Az alábbi szakaszok az ügyfélkódtár telepítésének különböző módjait ismertetik.

Telepítés npm használatával

A Visual Studio esetében futtassa az alábbi parancsokat a Package Manager-konzolról a gyökérmappában. A Visual Studio Code esetében futtassa az alábbi parancsokat az integrált terminálról.

npm init -y
npm install @microsoft/signalr

Az npm telepíti a csomag tartalmát a node_modules\@microsoft\signalr\dist\browser mappába. Hozzon létre egy új , signalr nevű mappát a wwwroot\lib mappában. Másolja a fájlt a signalr.jswwwroot\lib\signalr mappába.

Hivatkozzon a SignalR JavaScript-klienst az <script> elemben. Például:

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

Tartalomkézbesítési hálózat (CDN) használata

Ha az ügyfélkódtárat az npm előfeltétele nélkül szeretné használni, hivatkozzon az ügyfélkódtár CDN által üzemeltetett példányára. Például:

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

Az ügyfélkódtár a következő CDN-eken érhető el:

Telepítés a LibManrel

A LibMan a CDN-en tárolt ügyfél-oldali könyvtár adott fájljainak telepítésére használható. Például csak az összetömörített JavaScript fájlt adja hozzá a projekthez. Erről a megközelítésről további információt az SignalR ügyfélkódtár hozzáadása című témakörben talál.

Csatlakozás központhoz

Az alábbi kód létrehoz és elindít egy kapcsolatot. A központ neve nem érzékeny a kis- és nagybetűkre.

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

Forrásközi kapcsolatok

A böngészők általában a kért oldallal megegyező tartományból töltik be a kapcsolatokat. Vannak azonban olyan esetek, amikor egy másik tartományhoz való csatlakozásra van szükség.

Important

Az ügyfélkódnak relatív URL-cím helyett abszolút URL-címet kell használnia. Változtassa meg .withUrl("/chathub")-t .withUrl("https://myappurl/chathub")-re.

Ha meg szeretné akadályozni, hogy egy rosszindulatú webhely bizalmas adatokat olvasson egy másik helyről, a rendszer alapértelmezés szerint letiltja a többhelyes kapcsolatokat . A forrásközi kérés engedélyezéséhez engedélyezze azt az Startup osztályban:

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

A hívásközpont metódusai az ügyféltől

A JavaScript-ügyfelek nyilvános metódusokat hívnak meg a hubokon a HubConnectionmeghívási módszerével. A invoke metódus a következőt fogadja el:

  • A hub módszer neve.
  • A hub metódusban definiált argumentumok.

Az alábbi példában a hub metódusneve a következő SendMessage: . A második és a harmadik argumentum megegyezik a invoke a hub metódus user és message argumentumaival.

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

Note

A központi metódusok ügyfélről való meghívása csak akkor támogatott, ha az Azure SignalRService-t alapértelmezett módban használja. További információ: Gyakori kérdések (azure-signalr GitHub-adattár).

A invoke metódus Egy JavaScriptet Promisead vissza. A Promise a visszatérési értékkel (ha van ilyen) kerül feloldásra, amikor a kiszolgáló metódus visszatér. Ha a kiszolgálón lévő metódus hibát jelez, a Promise rendszer a hibaüzenettel elutasítja a metódust. Az ilyen esetek kezelésére használhatja async és a awaitPromise valamint then metódusokat.

A JavaScript-ügyfelek nyilvános metódusokat is meghívhatnak a hubokon a küldésiHubConnectionmetóduson keresztül. A invoke metódustól eltérően a send metódus nem várja meg a kiszolgáló válaszát. A send metódus Egy JavaScriptet Promisead vissza. A Promise probléma akkor szűnik meg, ha az üzenet el lett küldve a kiszolgálónak. Ha hibaüzenet jelenik meg az üzenet küldésekor, a Promise rendszer a hibaüzenettel együtt elutasítja az üzenetet. Az ilyen esetek kezelésére használhatja async és a awaitPromise valamint then metódusokat.

Note

A send használata nem várja meg, amíg a kiszolgáló megkapja az üzenetet. Következésképpen nem lehet adatokat vagy hibákat visszaadni a kiszolgálóról.

Az ügyfél metódusokat a hubról hívja

Ha üzeneteket szeretne fogadni a központból, definiáljon egy metódust az on metódussal a HubConnection.

  • A JavaScript-ügyfélmetódus neve.
  • A hub által a metódusnak megadott argumentumok.

Az alábbi példában a metódus neve .ReceiveMessage Az argumentumnevek user és message:

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

Az előző kód connection.on akkor fut le, amikor a kiszolgálóoldali kód meghívja azt a SendAsync metódus használatával:

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

SignalR meghatározza, hogy melyik kliens metódust kell meghívni a metódus nevének és argumentumainak SendAsync és connection.on egyeztetésével.

Note

A legjobb gyakorlatként hívja meg a start metódust a HubConnection után, miután on. Ezzel biztosítja, hogy a kezelők regisztrálva legyenek az üzenetek fogadása előtt.

Hibakezelés és naplózás

A try és catch használatával, valamint a async és await mellett az ügyféloldali hibák kezeléséhez alkalmazza a Promisecatch metódust. A böngésző konzolján megjelenő hibák kimenetére használható console.error :

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

Állítsa be az ügyféloldali naplókövetést úgy, hogy átad egy naplózót és egy eseménytípust a naplózáshoz a kapcsolat létrehozásakor. Az üzenetek a megadott naplószinttel illetve afeletti naplószintekkel kerülnek naplózásra. Az elérhető naplószintek a következők:

  • signalR.LogLevel.Error:Hibaüzenetek. Csak az üzeneteket naplózza Error .
  • signalR.LogLevel.Warning: Figyelmeztető üzenetek a lehetséges hibákról. Naplóz Warning, és Error üzeneteket.
  • signalR.LogLevel.Information: Állapotüzenetek hibák nélkül. Naplók Information, Warning és Error üzenetek.
  • signalR.LogLevel.Trace: Nyomkövetési üzenetek. Mindent naplóz, beleértve a központ és az ügyfél között szállított adatokat is.

A naplószint konfigurálásához használja a HubConnectionBuilderconfigureLogging metódusát. A rendszer naplózza az üzeneteket a böngészőkonzolon:

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

Ügyfelek újracsatlakoztatása

Automatikus újracsatlakozás

A JavaScript-ügyfél SignalR konfigurálható úgy, hogy automatikusan újracsatlakozjon a withAutomaticReconnectHubConnectionBuilder metódusával. Alapértelmezés szerint nem fog automatikusan újracsatlakozni.

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

Paraméterek nélkül úgy konfigurálja az ügyfelet, withAutomaticReconnect() hogy várjon 0, 2, 10 és 30 másodpercet, mielőtt megpróbálná az újracsatlakozási kísérleteket, és négy sikertelen kísérlet után leáll.

Mielőtt újracsatlakozási kísérleteket indítanának, a HubConnection rendszer átvált az HubConnectionState.Reconnecting állapotra, és elindítja a onreconnecting visszahívásokat az Disconnected állapotra való áttérés és a visszahívások onclose automatikus újracsatlakozás HubConnection nélküli konfigurálása helyett. Ezzel figyelmeztetheti a felhasználókat, hogy megszakadt a kapcsolat, és letilthatja a felhasználói felület elemeit.

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

Ha az ügyfél sikeresen újracsatlakozik az első négy kísérleten belül, a HubConnection rendszer visszaáll az Connected állapotra, és visszahívja a onreconnected visszahívásokat. Ez lehetőséget biztosít arra, hogy tájékoztassa a felhasználókat a kapcsolat újbóli létrejöttéről.

Mivel a kapcsolat teljesen újnak tűnik a kiszolgáló számára, a rendszer újat connectionId biztosít a onreconnected visszahíváshoz.

Warning

A onreconnected visszahívás paramétere connectionId nem lesz definiálva, ha a HubConnectionegyeztetés kihagyására lett konfigurálva.

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() nem konfigurálja a HubConnection kezdeti indítási hibák újrapróbálkozását, ezért az indítási hibákat manuálisan kell kezelni:

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

Ha az ügyfél az első négy kísérletében nem sikerül újracsatlakozni, az HubConnectionDisconnected állapotra vált, és aktiválja a visszahívásokat . Ez lehetőséget biztosít arra, hogy tájékoztassa a felhasználókat arról, hogy a kapcsolat véglegesen megszakadt, és javasoljuk a lap frissítését:

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

Ha egyéni számú újracsatlakozási kísérletet szeretne konfigurálni a kapcsolat bontása vagy módosítása előtt, withAutomaticReconnect fogadja el az ezredmásodperc késleltetését jelző számtömböt, hogy az egyes újracsatlakozási kísérletek megkezdése előtt várakozzon.

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

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

Az előző példa úgy konfigurálja a HubConnection kapcsolatot, hogy a kapcsolat megszakadása után azonnal megkísérlje az újracsatlakozást. Ez az alapértelmezett konfigurációra is igaz.

Ha az első újracsatlakozási kísérlet meghiúsul, a második újracsatlakozási kísérlet is azonnal elindul, ahelyett, hogy 2 másodpercet várna, mint az alapértelmezett konfigurációban.

Ha a második újracsatlakozási kísérlet meghiúsul, a harmadik újracsatlakozási kísérlet 10 másodpercen belül megkezdődik, ami ismét az alapértelmezett konfigurációhoz hasonló.

Az egyéni viselkedés ezután ismét eltér az alapértelmezett viselkedéstől azáltal, hogy a harmadik újracsatlakozási kísérlet meghiúsulása után leáll, ahelyett, hogy újabb 30 másodpercen belül próbálkozna újracsatlakozási kísérlettel, mint az alapértelmezett konfigurációban.

Ha még jobban szeretné szabályozni az automatikus újracsatlakozási kísérletek időzítését és számát, withAutomaticReconnect fogadja el az IRetryPolicy interfészt implementáló objektumot, amelynek egyetlen metódusa van elnevezve nextRetryDelayInMilliseconds.

nextRetryDelayInMilliseconds egyetlen argumentumot vesz fel a típussal RetryContext. A RetryContext három tulajdonsága: previousRetryCount, elapsedMilliseconds és retryReason, amelyek a number, a number és a Error. Az első újracsatlakozási kísérlet előtt mind a previousRetryCount, mind a elapsedMilliseconds nulla lesz, és a retryReason lesz az a hiba, ami a kapcsolat elvesztését okozta. Minden sikertelen újrapróbálkozási kísérlet previousRetryCount után a rendszer egy-egy lépéssel növekszik, a rendszer úgy frissül, elapsedMilliseconds hogy az tükrözze az újracsatlakozással töltött időt ezredmásodpercben, és az retryReason a hiba lesz, amely az utolsó újracsatlakozási kísérlet meghiúsulását okozta.

nextRetryDelayInMilliseconds vagy egy számot kell visszaadnia, amely az újracsatlakozási kísérlet előtt várandó ezredmásodpercek számát jelöli, vagy null értékét, ha az HubConnection újracsatlakozást le kell állítani.

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

Másik lehetőségként írhat olyan kódot is, amely manuálisan csatlakoztatja újra az ügyfelet a Manuális újracsatlakozás című témakörben leírtak szerint.

Manuális újracsatlakozás

Az alábbi kód egy tipikus manuális újracsatlakozási megközelítést mutat be:

  1. A kapcsolat elindításához létrejön egy függvény (ebben az esetben a start függvény).
  2. Hívja meg a start függvényt a kapcsolat eseménykezelőjében onclose .
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

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

Az éles implementációk általában exponenciális visszatartást használnak, vagy adott számú alkalommal újrapróbálkoznak.

Böngésző alvó fül

Egyes böngészők lapfagyasztási vagy alvó funkcióval rendelkeznek az inaktív lapok számítógép-erőforrás-használatának csökkentéséhez. Ez a kapcsolatok bezárását okozhatja SignalR , és nemkívánatos felhasználói élményt eredményezhet. A böngészők heurisztikus megoldásokkal derítik ki, hogy alvó állapotba kell-e helyezni egy lapot, például:

  • Hang lejátszása
  • Webes zárolás megtartása
  • IndexedDB Zárolás tartása
  • USB-eszközhöz való csatlakozás
  • Videó vagy hang rögzítése
  • Tükrözés
  • Ablak vagy kijelző rögzítése

Note

Ezek a heurisztikusok idővel változhatnak, vagy eltérhetnek a böngészők között. Ellenőrizze a támogatási mátrixot, és állapítsa meg, hogy melyik módszer működik a legjobban a forgatókönyvekhez.

Az alkalmazás alvó állapotba helyezésének elkerülése érdekében az alkalmazásnak aktiválnia kell a böngésző által használt heurisztika egyikét.

Az alábbi példakód bemutatja, hogyan használhat webzárat egy lap ébren tartásához és a váratlan kapcsolatlezárás elkerüléséhez.

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

Az előző példakód esetében:

  • A webzárak kísérleti jellegűek. A feltételes ellenőrzés megerősíti, hogy a böngésző támogatja a webzárolásokat.
  • Az ígéret feloldójának (lockResolver) tárolása úgy történik, hogy a zárolás feloldható legyen, amikor elfogadható, hogy a lap alvó állapotba kerüljön.
  • A kapcsolat bezárásakor a zárolás hívással lockResolver()feloldódik. A zárolás feloldásakor a lap alvó állapotba kerül.

További erőforrások