實現輸入提示 layui_ASP.NET Core SignalR :學習消息通訊,實現一個消息通知

什么是 SignalR

目前我用業余時間正在做一個博客系統,其中有個功能就是評論通知,就是假如A用戶評論B用戶的時候,如果B用戶首頁處于打開狀態,那么就會提示B用戶有未讀消息。暫時用SignalR來實現這個功能。我也是看了兩天的資料才明白怎么去使用。

關于SignalR的理論知識可以去官網或者百度,我這里只是結合自己的功能來分享下,如果有錯,請原諒指出。

下載js

SignalR是需要微軟提供的js,因為我的項目是前后端分離的,所以我是單獨下載到一個文件夾,然后復制js到我的前端項目里。只需要signalr.js

頁面加載創建連接

//創建連接  var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();//ajax執行成功執行  $.ajax({success: function (response) {                                   connection.start().then(function () {                            connection.invoke('SetConnectionMaps', response.data.account);                    }                },            });

首先你要了解到SignalR基本運行的原理,官網:https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio

你可以直接繼承Hub這個類,我這里用的是強類型Hub,我就是為了讓前端和后端統一下。剛開始Hub我糾結了好久,不知道怎么用,最后我手動做了下,認為它只是為了方便前端和后端統一。

如果你只是簡單的繼承Hub類,你就必須調用SendAsync方法,并且指定前端接收觸發的方法名稱“InvokeMessage”,如果你后端和前端名字對應不上,就會有問題。

public class SingalrService : Hub    {private ISingalrSvc _singalrSvc;public SingalrService(ISingalrSvc singalrSvc)        {            _singalrSvc = singalrSvc;        }public async Task SendMessageAsync(Message sendMessage)        {await Clients.All.SendAsync("InvokeMessage",sendMessage);        }public void SetConnectionMaps(string account)        {string connectionid = Context.ConnectionId;            _singalrSvc.SetConnectionMaps(connectionid, account);        }public override Task OnDisconnectedAsync(Exception exception)        {            _singalrSvc.Remove(Context.ConnectionId);return base.OnDisconnectedAsync(exception);        }    }

所以有了強類型Hub,自己定義一個接口,提過方法InvokeMessage供前前端調用。

/// /// 客戶端js調用方法/// public interface ISingalrClient    {Task InvokeMessage(Message sendMessage);    }public class SingalrService : Hub    {private ISingalrSvc _singalrSvc;public SingalrService(ISingalrSvc singalrSvc){            _singalrSvc = singalrSvc;        }public void SetConnectionMaps(string account){string connectionid = Context.ConnectionId;            _singalrSvc.SetConnectionMaps(connectionid, account);        }//連接中斷時執行,微軟這樣描述的://重寫 OnDisconnectedAsync 虛方法,以便在客戶端斷開連接時執行操作。如果客戶端故意斷開連接(例如,通過調用 connection.stop()),exception 參數將 null。//但是,如果客戶端由于錯誤(例如網絡故障)而斷開連接,則 exception 參數將包含描述失敗的異常public override Task OnDisconnectedAsync(Exception exception){            _singalrSvc.Remove(Context.ConnectionId);return base.OnDisconnectedAsync(exception);        }    }

這個時候一個用戶打開了首頁,然后首頁有個js方法來初始化連接,同一個頁面內的connectionid是一樣的,每次刷新或新打開一個窗口的新頁面的connectionid是不一樣的,并且你刷新頁面或者關掉會認為是連接中斷,會執行OnDisconnectedAsync方法,這個方法時SingalR自帶的,它是個虛方法,你也可以重寫,就像我一樣。我這里的代碼邏輯是將連接id和當前登錄人作為鍵值對存入內存,然后用戶關掉頁面就會執行OnDisconnectedAsync方法,將相關的coonectionid從內存刪掉:??

layui.use(['element', 'layer'], function () {var element = layui.element;            element.render('nav');            initLoad();//初始化連接,每個頁面的connection的connectionid是一樣的,但是每次創建的不一樣var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();//綁定后臺觸發的方法,前面已經講過了,具體業務還沒實現,            connection.on('InvokeMessage', (reviceMessage) => {var v = reviceMessage;            });            $.ajax({url: url + 'user/userInfo',type: 'get',dataType: 'json',beforeSend: function (xhr) {                    doBeforeSend(xhr);                },success: function (response) {if (response.code == '1') {                        $("#nologin").show();                        $("#user").hide();                    }else {                        $("#nologin").hide();                        $("#user").show();                        $("#photo").attr('src', response.data.headPhoto);//連接開始                        connection.start().then(function () {//調用后臺方法,不是api接口,將當前登錄人賬號傳過去                            connection.invoke('SetConnectionMaps', response.data.account);                        })                    }                },complete: function (xhr) {                    doComplete(xhr);                },            });        });

這個時候連接已經創建完成,并且用戶并沒有關閉首頁,連接一直處于連接狀態。這個時候另一個用戶打開了一篇文章詳情,并且對它評論提交內容后,我讓它觸發了一個連接SingalR的事件,

   form.on('submit(review)', function (data) {        loading = layer.load(2);var commentModel = {'Content': data.field.desc,        }        $.ajax({url: url + 'article/review/' + id,contentType: 'application/json; charset=utf-8',type: 'post',datatype: 'json',data: JSON.stringify(commentModel),beforeSend: function (xhr) {                doBeforeSend(xhr);            },success: function (response) {if (response.code == 0) {//另一個用戶創建了連接var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();                    connection.start().then(function () {var apiRoute=url+'Singalr/admin';//admin是我設置死的,實際應該是自己判斷,會調用下面的api,[Route("api/[controller]")],SingalR也是支持api調用的var token=localStorage.getItem('token');                        fetch(apiRoute,{method:'get',headers:{'Authorization':'Bearer ' + token                            }                        })                        event.preventDefault();                    })                    layer.close(loading);                } else {                    layer.close(loading);                    layer.msg("評論失敗", {icon: 5                    });                }            },complete: function (xhr) {                doComplete(xhr);            },        })
[ApiController]public class SingalrController : ControllerBase{private IHubContext _hubContext;private ISingalrSvc _singalrSvc;public SingalrController(IHubContext hubContext, ISingalrSvc singalrSvc)  {      _hubContext = hubContext;      _singalrSvc = singalrSvc;  }/// /// 查詢未處理數量/// /// ///   [HttpGet("{account}")]public async Task NewsCount(string account)  {      Message sendMessage = new Message();      sendMessage.Data = "11";//剛已經講了,用戶加載首頁的時候已經把connectionid和account存入到了內存里面,現在再取用戶相關的connectionID,如果直接調用Clinets.ALL就是給所有客戶端發送消息      IReadOnlyList connectionIds = (IReadOnlyList)_singalrSvc.GetConnectionIds(account);await _hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage);  }}

這個時候調用了這個api執行了里面的_hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage),connectionIds是根據業務邏輯所判斷的觸發的那些客戶端;然后前端會根據方法名響應對應的js代碼,如下

layui.use(['element', 'layer'], function () {var element = layui.element;            element.render('nav');            initLoad();var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();
//我認為是一個用來偵聽服務端方法的js connection.on('InvokeMessage', (reviceMessage) => {var v = reviceMessage;
//響應后端方法成功后,就開始自己的業務邏輯 }); $.ajax({ url: url + 'user/userInfo',type: 'get', dataType: 'json', beforeSend: function (xhr) { doBeforeSend(xhr); }, success: function (response) {if (response.code == '1') { $("#nologin").show(); $("#user").hide(); }else { $("#nologin").hide(); $("#user").show(); $("#photo").attr('src', response.data.headPhoto); connection.start().then(function () { connection.invoke('SetConnectionMaps', response.data.account); }) } }, complete: function (xhr) { doComplete(xhr); }, }); });

原文地址:

https://www.cnblogs.com/MrHanBlog/p/11996689.html

58dc8f7cdb335d45da757307739053f0.png

點擊【在看】與好友一起分享

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/534277.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/534277.shtml
英文地址,請注明出處:http://en.pswp.cn/news/534277.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux課堂筆記(5)

vi編輯器 1,vi版本:vi —— vim ps:查看進程 進程 ID 時間 終端 進程名稱 ps -t 終端(查看指定終端進程) vi 回車(提示vi版本信息) 2,vi特點 (1)…

兩個字和三個字一樣寬_武漢國慶出行 記好三個字

武漢國慶出行國慶黃金周帶你一起見證奇跡樂在武漢國慶去哪兒玩?記住:三 個 字歡樂谷記住【歡樂谷】三個字,你就不會迷路!不算白來。歡樂谷有啥好?免費!國慶期間,歡樂谷面向全國人民免費開放&…

linux課堂筆記(6)

設置文件訪問權限: 1,通過字母設置:參數 字母 (1)用戶類型: u 擁有者 g 同組用戶 o 其他用戶 a所有用戶 (2)權限:r 讀 w 寫 x執行 注:目錄權…

什么標簽用于在表單中構建復選框_UI/UX筆記之如何設計好表單

原文鏈接:UI/UX筆記之如何設計好表單 | 須臾所學免費設計資源網?presentationvip.com無論是注冊流程,多視圖步驟程序還是單調的數據輸入界面,表單都是數字產品設計中最重要的組成部分之一。本文重點介紹表單設計的常見事項。請記住&#xff…

linux課堂筆記(7)

編譯器&#xff1a;gcc 格式&#xff1a;gcc [參數] <源程序> gcc test.c 注&#xff1a;默認生成可執行程序a.out&#xff08;windows默認test.exe&#xff09; ./a.out gcc -o 可執行文件 源程序 gcc -o test.exe test.c&#xff08;windows&#xff09; g…

mqtt 發送消息過多_阿里云MQTT服務端注解式消息處理分發與同步調用實踐小結

一、前言前段時間公司預研了設備app端與服務端的交互方案&#xff0c;出于多方面考量最終選用了阿里云的微服務隊列MQTT方案&#xff0c;基于此方案&#xff0c;本人主要實踐有&#xff1a;1. 封裝了RocketMQ實現MQTT訂閱與發布的實現細節&#xff1b;2. 實現了注解式分發處理&…

linux課堂筆記(8)

磁盤分區工具&#xff08;parted&#xff09; 1&#xff0c;語法&#xff1a; parted 磁盤 注&#xff1a;磁盤類型&#xff08;根據接口劃分&#xff09; &#xff08;1&#xff09;IDE-hd&#xff0c;hda&#xff0c;hdc&#xff08;光驅&#xff09;&#xff0c;hdd 加…

css引入矢量圖標_WEB 項目開發中的圖標管理解決方案

相信很多前端開發人員在項目開發過程中都會遇到這樣一個問題&#xff1a;頁面的圖標發生改動&#xff0c;需要往圖標文件中追加新的圖標&#xff0c;卻因為圖標文件已經打包好而無從下手&#xff0c;重新制作一份圖標文件吧&#xff0c;要考慮替換整個項目的圖標&#xff0c;工…

判斷按鍵值_Pygame(九)按鍵事件(2)

Pygame(九)按鍵事件(2)前情提要前情提要作業解析完整代碼# /usr/bin/python3# Author: 愛編程的章老師# Time: 2021/1/7 0007# E-mail: Bluesand2010163.comimport pygame, sys, timefrom random import randintdef homework():作業 擋板接球 一個寬100 ,高10的棕色擋板,…

動態添加input_前端提效必備:動態模版生成

前言在日常開發中&#xff0c;我們需要不停的新建頁面和組件。以 Vue 項目為例&#xff0c;我們在新建一個頁面的時候&#xff0c;需要經歷一遍又一遍重復的過程&#xff1a;1、先新建一個文件夾2、然后新建一個 .vue 文件&#xff0c;寫上 、", "" ],"…

在dom最前面插入_JavaScript中的DOM

1. 關于DOM文檔對象模型(DocumentObject Model)&#xff0c;是基于瀏覽器編程的一套API接口&#xff0c;W3C出臺的推薦標準&#xff0c;每個瀏覽器都有一些細微的差別&#xff0c;其中以Mozilla(火狐)的瀏覽器最與標準接近。通過 DOM&#xff0c;可以訪問所有的 HTML元素&#…

python 快速刪除程序_如何快速一次性卸載所有python包(第三方庫)呢

很多時候我們都會有一個麻煩事&#xff0c;就是打開pycharm或者VScode等的時候&#xff0c;都有可能因為自己電腦上面安裝的第三方模塊過多&#xff0c;導致電腦很卡&#xff0c;風扇轉速不停地增加&#xff0c;這時候我們就會想去卸載一些不太用得著的第三方模塊&#xff0c;但…

python正則表達式修飾符_Python正則表達式

正則表達式是一個特殊的字符序列&#xff0c;它能幫助你方便的檢查一個字符串是否與某種模式匹配。re 模塊使 Python 語言擁有全部的正則表達式功能。compile 函數根據一個模式字符串和可選的標志參數生成一個正則表達式對象。該對象擁有一系列方法用于正則表達式匹配和替換。r…

當代最值得收藏的畫家作品_當代最具潛力和收藏價值的十大畫家

原標題&#xff1a;當代最具潛力和收藏價值的十大畫家當代從事繪畫的人成千上萬&#xff0c;哪些名家作品值得收藏&#xff1f;當前都有哪些“潛力股”&#xff0c;相關專家綜合市場分析&#xff0c;純從藝術水準上列出值得收藏的“潛力股”&#xff0c;供愛好書畫收藏的各界人…

備抵附加賬戶的期末余額_會計賬戶的分類(二)

待攤費用賬戶的格式和運用方法同盤存類賬戶&#xff0c;即&#xff1a;期初如果有余額在借方&#xff0c;本期發生額的增加數在借方&#xff0c;本期發生額的減少數在貸方&#xff0c;期末如果有余額在借方。預提費用賬戶是指用來核算和監督按規定預先提取計入當期&#xff0c;…

mysql union all 別名_mysql union和union all

如下先創建2個表&#xff0c;aa bb.CREATE table aa(uid int(20) not null,name VARCHAR(30) not null)engineinnodb default charsetutf8mb4 COLLATE utf8mb4_general_ci;INSERT INTO aa(uid, name) VALUES (10, 張芳);INSERT INTO aa(uid, name) VALUES (11, 王凱);INSERT IN…

MySQL不走聯合索引_mysql group by 多列優化思路?為什么不走聯合索引?

explain SELECT a, b, COUNT(*) FROM tbnameGROUP BY a, border by a DESClimit 1a 和 b 列已經設置聯合索引&#xff0c; 為什么這種操作也會執行全表掃描呢&#xff1f;explain SELECT a, b FROM tbnameGROUP BY a, border by a DESC去掉 COUNT 和 limit 則走索引沒有掃描&am…

mysql ddl 鎖_MySQL Online DDL導致全局鎖表案例分析

MySQL Online DDL導致全局鎖表案例分析我這邊遇到了什么問題?線上給某個表執行新增索引SQL, 然后整個數據CPU打到100%, 連接數暴增到極限, 最后導致所有訪問數據庫的應用都奔潰.SQL如下:ALTER TABLE bookADD INDEX idx_sub_title (sub_title ASC);能看到什么?10063293, root,…

ci框架 亂碼 mysql_mysql容器亂碼問題

在docker-compose.yml文件中定義mysql導入utf-8的萬國碼services:mysql:image:mysql:5.7# command: [--character-set-serverutf8mb4, --collation-serverutf8mb4_unicode_ci]volumes:-./data/docker/mysql:/var/lib/mysql-./mysql/:/docker-entrypoint-initdb.d/-./conf/mys…

mysql分表 查詢 優化_MySQL性能管理及架構(查詢優化、分庫分表)一遍文章搞定...

相關配置參數&#xff1a;slow_query_log # 啟動停止記錄慢查日志&#xff0c;慢查詢日志默認是沒有開啟的可以在配置文件中開啟(on)slow_query_log_file # 指定慢查日志的存儲路徑及文件&#xff0c;日志存儲和數據從存儲應該分開存儲long_query_time # 指定記錄慢查詢日志SQL…