ASP.NET Core SignalR 系列(三)- JavaScript 客戶端

来源:https://www.cnblogs.com/xyh9039/archive/2023/07/13/17539560.html
-Advertisement-
Play Games

本章將和大家分享 ASP.NET Core SignalR 中的 JavaScript 客戶端。ASP.NET Core SignalR JavaScript 客戶端庫使開發人員能夠調用伺服器端SignalR中心代碼。 ...


本章將和大家分享 ASP.NET Core SignalR 中的 JavaScript 客戶端。ASP.NET Core SignalR JavaScript 客戶端庫使開發人員能夠調用伺服器端SignalR中心代碼。

本文大部分內容摘自微軟官網:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-7.0&tabs=visual-studio

廢話不多說,下麵我們直接進入本章主題: 

1、安裝 SignalR 客戶端包

ASP.NET Core 共用框架中包含 SignalR 伺服器庫。JavaScript 客戶端庫不會自動包含在項目中。對於此教程,使用庫管理器 (LibMan) 從 unpkg 獲取客戶端庫。unpkg 是一個快速的全局內容分髮網絡,適用於 npm 上的所有內容。

在 Visual Studio “解決方案資源管理器” 中,右鍵單擊項目,然後選擇 “添加” => “客戶端庫”。

在“添加客戶端庫”對話框中:

  • 為“提供程式”選擇“unpkg”。
  • 對於“庫”,請輸入 @microsoft/signalr@latest。
  • 選擇“選擇特定文件”,展開“dist/browser”文件夾,然後選擇 signalr.js 和 signalr.min.js。
  • 將“目標位置”設置為 wwwroot/js/signalr/。(可根據實際情況進行修改)
  • 選擇“安裝” 。

LibMan 會創建 wwwroot/js/signalr 文件夾並將所選文件複製到該文件夾下。

2、連接到中心

以下代碼創建並啟動連接。中心的名稱不區分大小寫:

//第一個參數:載入依賴模塊,可以是require_config中定義的短模塊名,也可以是完整的模塊路徑(去掉.js尾碼名,根目錄為require_config中設置的baseUrl)
//第二個參數:執行載入完後的回調函數
require(['../common/base', 'jquery', 'signalr'], function (base, $, signalR) {
    let axios = base.axios;

    var vm = new base.vue({
        el: '#app', //掛載點
        mixins: [base.mixin], //混入,類似基類的概念
        data: {
            connectionSignalR: '', //SignalR連接
            user: '',
            message: '',
            msgList: []
        },
        //created鉤子函數
        created: function () {
            this.initSignalR(); //初始化SignalR
        },
        //mounted鉤子函數
        mounted: function () {
            //console.log('This is index mounted');
        },
        //方法
        methods: {
            //初始化SignalR
            initSignalR: function () {
                var _this = this;
                var domain = "http://localhost:5296"; //網站功能變數名稱

                //創建連接
                _this.connectionSignalR = new signalR.HubConnectionBuilder()
                    .withUrl(domain + "/chatHub") //跨域的話必須使用絕對路徑
                    .configureLogging(signalR.LogLevel.Error) //配置日誌等級
                    //自動重新連接,嘗試每次重新連接之前預設分別等待 0、2、10 和 30 秒。嘗試四次失敗後,它會停止嘗試重新連接。
                    .withAutomaticReconnect() //.withAutomaticReconnect([0, 2000, 10000, 30000]) 
                    .build();
                /*
                    日誌等級:
                    signalR.LogLevel.Error:錯誤消息。 Error僅記錄消息。
                    signalR.LogLevel.Warning:有關潛在錯誤的警告消息。 日誌 Warning 和 Error 消息。
                    signalR.LogLevel.Information:無錯誤的狀態消息。 日誌 Information 、 Warning 和 Error 消息。
                    signalR.LogLevel.Trace:跟蹤消息。 記錄所有內容,包括中心和客戶端之間傳輸的數據。
                */

                //監聽中心(服務端)發送的消息(服務端調用客戶端)(訂閱)
                //ReceiveMessage 是服務端調用客戶端的方法名
                _this.connectionSignalR.on("ReceiveMessage", function (user, message) {
                    _this.msgList.push({
                        user: user,
                        message: message
                    });
                });

                //啟動連接
                _this.connectionSignalR.start().then(function () {
                    //啟動連接後需要立即執行的邏輯
                    //document.getElementById("sendButton").disabled = false;
                }).catch(function (err) {
                    return console.error(err.toString());
                });
            },
            //發送消息
            sendMsg: function () {
                var _this = this;

                if (_this.message) {
                    //向中心(服務端)發送消息(客戶端調用服務端)
                    //SendMessage 是服務端定義的的方法
                    _this.connectionSignalR.invoke("SendMessage", _this.user, _this.message).catch(function (err) {
                        return console.error(err.toString());
                    });
                    _this.message = ''; //發送完清空消息
                }
            },
        }
    });
});

3、跨域連接(CORS)

通常,瀏覽器從與請求頁面相同的域載入連接。但是,有時需要連接到另一個域。

發出跨域請求時,客戶端代碼必須使用絕對 URL 而不是相對 URL。對於跨域請求,需要將 .withUrl("/chathub") 修改為 .withUrl("https://{App domain name}/chathub") 。

為了防止惡意站點從另一站點讀取敏感數據,預設情況下禁用跨域連接。若要允許跨源請求,請啟用 CORS:

using SignalRChat.Hubs;

namespace SignalRChat
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);

            //服務註冊(往容器中添加服務)
            // Add services to the container.
            builder.Services.AddControllersWithViews();
            builder.Services.AddSignalR(); //註冊中心所需的 SignalR 服務

            //設置允許跨域
            builder.Services.AddCors(options =>
            {
                options.AddDefaultPolicy(
                    builder =>
                    {
                        builder.WithOrigins("http://localhost:5296", "http://localhost:8080")
                            .AllowAnyHeader()
                            .WithMethods("GET", "POST")
                            .AllowCredentials();
                    });
            });

            var app = builder.Build();

            //配置Http請求處理管道
            // Configure the HTTP request pipeline.
            if (!app.Environment.IsDevelopment())
            {
                app.UseExceptionHandler("/Home/Error");
            }
            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthorization();

            //設置允許跨域
            // UseCors must be called before MapHub. //必須在 MapHub 之前調用 UseCors 方法
            app.UseCors();

            //配置MVC路由
            app.MapControllerRoute(
                name: "areas",
                pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
            app.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");

            //配置SignalR終結點
            app.MapHub<ChatHub>("/chatHub"); //中心
            app.MapHub<StronglyTypedChatHub>("/stronglyTypedChatHub"); //強類型中心

            app.Run();
        }
    }
}

必須在 MapHub 之前調用 app.UseCors(); 方法。

4、從客戶端調用中心方法

JavaScript 客戶端通過 HubConnection 的 invoke 方法調用中心的公共方法。invoke 方法接受:

  • 中心方法的名稱。
  • 中心方法中定義的任何參數。

在以下突出顯示的代碼中,中心上的方法名稱為 SendMessage。傳遞到 invoke 的第二個和第三個參數映射到中心方法的 user 和 message 參數:

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

僅在預設模式下使用 Azure SignalR 服務 時,才支持從客戶端調用中心方法。

invoke 方法返回 JavaScript Promise。 伺服器上的方法返回時,Promise 通過返回值(如果有)進行解析。如果伺服器上的方法引發錯誤,Promise 會被拒絕並顯示錯誤消息。使用 async 和 await 或 Promise 的 then 和 catch 方法來處理這些情況。

JavaScript 客戶端還可以通過 HubConnection 的 send 方法調用中心的公共方法。與 invoke 方法不同,send 方法不會等待來自伺服器的響應。send 方法返回 JavaScript Promise。當消息發送到伺服器後,會解析 Promise。如果發送消息時出錯,Promise 會被拒絕並顯示錯誤消息。使用 async 和 await 或 Promise 的 then 和 catch 方法來處理這些情況。

使用 send 不會等到伺服器收到消息。因此,無法從伺服器返回數據或錯誤。

5、從中心調用客戶端方法

若要接收來自中心的消息,請使用 HubConnection 的 on 方法定義方法:

  • JavaScript 客戶端方法的名稱。
  • 中心傳遞給方法的參數。

在下麵的示例中,方法名稱為 ReceiveMessage。參數名稱為 user 和 message:

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

connection.on 中的上述代碼在伺服器端代碼使用 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 通過匹配在 SendAsync 和 connection.on 中定義的方法名稱和參數來確定要調用的客戶端方法。

客戶端的最佳做法是在 on 之後 調用 HubConnection 的 start 方法。這樣做可確保在收到任何消息之前註冊處理程式。

6、錯誤處理和日誌記錄

使用 console.error 在客戶端無法連接或發送消息時將錯誤輸出到瀏覽器的控制台:

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

在建立連接時,通過傳遞記錄器和要記錄的事件類型來設置客戶端日誌跟蹤。可用的日誌級別如下所示:

  • signalR.LogLevel.Error:錯誤消息。僅記錄 Error 消息。
  • signalR.LogLevel.Warning:有關潛在錯誤的警告消息。記錄 Warning 和 Error 消息。
  • signalR.LogLevel.Information:沒有錯誤的狀態消息。記錄 Information、Warning 和 Error 消息。
  • signalR.LogLevel.Trace:跟蹤消息。記錄所有內容,包括在中心和客戶端之間傳輸的數據。

使用 HubConnectionBuilder 上的 configureLogging 方法配置日誌級別。消息將記錄到瀏覽器控制台:

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

7、重新連接客戶端

1)自動重新連接

預設情況下,它不會自動重新連接。如果需要自動重新連接,則可以將  SignalR 的 JavaScript 客戶端配置為使用 HubConnectionBuilder 上的 WithAutomaticReconnect 方法。

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

如果不使用任何參數,WithAutomaticReconnect 會將客戶端配置為每次嘗試重新連接之前分別等待 0、2、10 和 30 秒。嘗試四次失敗後,會停止嘗試重新連接。

配置自定義的重新連接嘗試次數,withAutomaticReconnect 會接受一個數字數組,表示在每次開始嘗試重新連接之前要等待的延遲(以毫秒為單位):

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

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

若要更好地控制自動重新連接嘗試的時間和次數,可以自行去微軟官網瞭解。

2)手動重新連接

下麵的代碼演示典型的手動重新連接方法:

  1. 創建函數(在本例中為 start 函數)以啟動連接。
  2. 在連接的 onclose 事件處理程式中調用 start 函數。
async function start() {
    try {
        await connection.start();
        console.log("SignalR Connected.");
    } catch (err) {
        console.log(err);
        setTimeout(start, 5000);
    }
};

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

生產實現通常使用指數退避或重試指定的次數。

8、瀏覽器睡眠選項卡

某些瀏覽器具有選項卡凍結或休眠功能,用於減少非活動選項卡的電腦資源使用量。 這可能會導致 SignalR 連接關閉,並可能導致不必要的用戶體驗。

瀏覽器使用啟發法判斷選項卡是否應進入睡眠狀態,下麵的代碼示例演示如何使用 Web Lock 將選項卡保持為喚醒狀態,並避免意外的連接關閉:

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

對於上述代碼示例:

  • Web Lock 是實驗性的。條件檢查可確認瀏覽器是否支持 Web Lock。
  • 存儲承諾解析程式 lockResolver,以便在選項卡進入睡眠狀態時可以釋放鎖。
  • 關閉連接時,通過調用 lockResolver() 釋放鎖定。釋放鎖定時,選項卡可進入睡眠狀態。

9、SignalR 信息推送的兩種通道

1)客戶端觸發推送,如下所示:

2)服務端觸發推送,如下所示:

至此本文就全部介紹完了,想要瞭解更多內容可參考微軟官網。

 

Demo源碼:

鏈接:https://pan.baidu.com/s/1U4IadFp-qThj0t3axrtNJA 
提取碼:bwb3

此文由博主精心撰寫轉載請保留此原文鏈接:https://www.cnblogs.com/xyh9039/p/17539560.html

版權聲明:如有雷同純屬巧合,如有侵權請及時聯繫本人修改,謝謝!!!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # 1.1 異常是什麼 python使用異常對象來表示異常狀態,併在遇到錯誤時引發異常。異常對象未被處理,程式將終止並顯示一條錯誤信息。 我們可以通過各種方法引發和捕獲錯誤,並採取對應措施。 # 1.2 將“錯誤”變成異常 自主地引發異常 ## 1.2.1 raise語句 我們通過預測異常可能發生的 ...
  • > 太陽🔆未起床,我去上集訓~ > > 坐著車🚗,到門口🚪,迷迷糊糊坐在電腦💻前~ > > 看一看題目,全都不會😭做! > > 摸電線🔋,開電閘,滋滋滋滋到閻王👼面前~ ### 閑聊一陣 emm,今天我被各種東西**虐**慘😭了! Why? 我媽讓我早上 $\texttt {6:00 ...
  • 我從大二上學期的時候學了數據結構,但是當時對數據結構的重要性並不太重視,直到在升大三的暑假,才意識到數據結構對以後學語言和找工作方面的重要性,所以亡羊補牢,為時未晚,嘗試著結合b站上王道考研數據結構課,來記錄自己對知識和代碼的理解。 數據結構學習的內容可以理解為,我們用代碼怎麼去把現實世界的問題高效 ...
  • java JDK安裝及配置 windows11 jdk-8u261-windows-x64.exe 1、點擊安裝,一路預設即可 2、設置系統環境變數 新建JAVA_HOME指明JDK安裝路徑,就是剛纔安裝時所選擇的路徑C:\Program Files\Java\jdk1.8.0_261,此路徑下包括 ...
  • 一、 描述 Spring Cloud Zuul是基於Netflix開源的Zuul項目構建而成,它作為微服務架構中的網關服務,主要用於實現動態路由、負載均衡和請求過濾等功能。 動態路由:Zuul根據預設的路由規則將進來的請求路由到相應的服務實例上。路由規則可以通過配置文件或代碼進行定義,接收到請求後, ...
  • ## 可以徹底告別手寫正則表達式了 這篇文章的目的是讓你能得到完美的正則表達式,而且還不用自己拼。 說到正則表達式,一直是令我頭疼的問題,這家伙一般時候用不到,等用到的時候發現它的規則是一點兒也記不住,`\d`表示一個數字,`\s`表示包括下劃線在內的任意單詞字元,也就是 `[A-Za-z0-9_] ...
  • 在筆者前幾篇文章中,我們使用彙編語言並通過自定位的方法實現了一個簡單的`MessageBox`彈窗功能,但由於彙編語言過於繁瑣在編寫效率上不僅要考驗開發者的底層功底,還需要寫出更多的指令集,這對於普通人來說是非常困難的,當然除了通過彙編來實現`ShellCode`的編寫以外,使用C同樣可以實現編寫,... ...
  • ## 前言 之前有用這個[MediaPipe.NET](https://github.com/vignetteapp/MediaPipe.NET) .NET包裝庫搞了手勢識別,豐富了稚暉君的[ElectronBot](https://github.com/peng-zhihui/ElectronBo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...