实现输入提示 layui_ASP.NET Core SignalR :学习消息通讯,实现一个消息通知
什么是 SignalR
目前我用業(yè)余時(shí)間正在做一個(gè)博客系統(tǒng),其中有個(gè)功能就是評論通知,就是假如A用戶評論B用戶的時(shí)候,如果B用戶首頁處于打開狀態(tài),那么就會提示B用戶有未讀消息。暫時(shí)用SignalR來實(shí)現(xiàn)這個(gè)功能。我也是看了兩天的資料才明白怎么去使用。
關(guān)于SignalR的理論知識可以去官網(wǎng)或者百度,我這里只是結(jié)合自己的功能來分享下,如果有錯,請?jiān)徶赋觥?/p>
下載js
SignalR是需要微軟提供的js,因?yàn)槲业捻?xiàng)目是前后端分離的,所以我是單獨(dú)下載到一個(gè)文件夾,然后復(fù)制js到我的前端項(xiàng)目里。只需要signalr.js
頁面加載創(chuàng)建連接
//創(chuàng)建連接 var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();//ajax執(zhí)行成功執(zhí)行 $.ajax({success: function (response) { connection.start().then(function () { connection.invoke('SetConnectionMaps', response.data.account); } }, });首先你要了解到SignalR基本運(yùn)行的原理,官網(wǎng):https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/signalr?view=aspnetcore-3.1&tabs=visual-studio
你可以直接繼承Hub這個(gè)類,我這里用的是強(qiáng)類型Hub,我就是為了讓前端和后端統(tǒng)一下。剛開始Hub我糾結(jié)了好久,不知道怎么用,最后我手動做了下,認(rèn)為它只是為了方便前端和后端統(tǒng)一。
如果你只是簡單的繼承Hub類,你就必須調(diào)用SendAsync方法,并且指定前端接收觸發(fā)的方法名稱“InvokeMessage”,如果你后端和前端名字對應(yīng)不上,就會有問題。
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); } }所以有了強(qiáng)類型Hub,自己定義一個(gè)接口,提過方法InvokeMessage供前前端調(diào)用。
/// /// 客戶端js調(diào)用方法/// 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); }//連接中斷時(shí)執(zhí)行,微軟這樣描述的://重寫 OnDisconnectedAsync 虛方法,以便在客戶端斷開連接時(shí)執(zhí)行操作。如果客戶端故意斷開連接(例如,通過調(diào)用 connection.stop()),exception 參數(shù)將 null。//但是,如果客戶端由于錯誤(例如網(wǎng)絡(luò)故障)而斷開連接,則 exception 參數(shù)將包含描述失敗的異常public override Task OnDisconnectedAsync(Exception exception){ _singalrSvc.Remove(Context.ConnectionId);return base.OnDisconnectedAsync(exception); } }這個(gè)時(shí)候一個(gè)用戶打開了首頁,然后首頁有個(gè)js方法來初始化連接,同一個(gè)頁面內(nèi)的connectionid是一樣的,每次刷新或新打開一個(gè)窗口的新頁面的connectionid是不一樣的,并且你刷新頁面或者關(guān)掉會認(rèn)為是連接中斷,會執(zhí)行OnDisconnectedAsync方法,這個(gè)方法時(shí)SingalR自帶的,它是個(gè)虛方法,你也可以重寫,就像我一樣。我這里的代碼邏輯是將連接id和當(dāng)前登錄人作為鍵值對存入內(nèi)存,然后用戶關(guān)掉頁面就會執(zhí)行OnDisconnectedAsync方法,將相關(guān)的coonectionid從內(nèi)存刪掉:??
layui.use(['element', 'layer'], function () {var element = layui.element; element.render('nav'); initLoad();//初始化連接,每個(gè)頁面的connection的connectionid是一樣的,但是每次創(chuàng)建的不一樣var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build();//綁定后臺觸發(fā)的方法,前面已經(jīng)講過了,具體業(yè)務(wù)還沒實(shí)現(xiàn), 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 () {//調(diào)用后臺方法,不是api接口,將當(dāng)前登錄人賬號傳過去 connection.invoke('SetConnectionMaps', response.data.account); }) } },complete: function (xhr) { doComplete(xhr); }, }); });這個(gè)時(shí)候連接已經(jīng)創(chuàng)建完成,并且用戶并沒有關(guān)閉首頁,連接一直處于連接狀態(tài)。這個(gè)時(shí)候另一個(gè)用戶打開了一篇文章詳情,并且對它評論提交內(nèi)容后,我讓它觸發(fā)了一個(gè)連接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) {//另一個(gè)用戶創(chuàng)建了連接var connection = new signalR.HubConnectionBuilder().withUrl('http://127.0.0.1:5000/chatHub').build(); connection.start().then(function () {var apiRoute=url+'Singalr/admin';//admin是我設(shè)置死的,實(shí)際應(yīng)該是自己判斷,會調(diào)用下面的api,[Route("api/[controller]")],SingalR也是支持api調(diào)用的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; }/// /// 查詢未處理數(shù)量/// /// /// [HttpGet("{account}")]public async Task NewsCount(string account) { Message sendMessage = new Message(); sendMessage.Data = "11";//剛已經(jīng)講了,用戶加載首頁的時(shí)候已經(jīng)把connectionid和account存入到了內(nèi)存里面,現(xiàn)在再取用戶相關(guān)的connectionID,如果直接調(diào)用Clinets.ALL就是給所有客戶端發(fā)送消息 IReadOnlyList connectionIds = (IReadOnlyList)_singalrSvc.GetConnectionIds(account);await _hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage); }}這個(gè)時(shí)候調(diào)用了這個(gè)api執(zhí)行了里面的_hubContext.Clients.Clients(connectionIds).InvokeMessage(sendMessage),connectionIds是根據(jù)業(yè)務(wù)邏輯所判斷的觸發(fā)的那些客戶端;然后前端會根據(jù)方法名響應(yīng)對應(yīng)的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();//我認(rèn)為是一個(gè)用來偵聽服務(wù)端方法的js connection.on('InvokeMessage', (reviceMessage) => {var v = reviceMessage;
//響應(yīng)后端方法成功后,就開始自己的業(yè)務(wù)邏輯 }); $.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
點(diǎn)擊【在看】與好友一起分享總結(jié)
以上是生活随笔為你收集整理的实现输入提示 layui_ASP.NET Core SignalR :学习消息通讯,实现一个消息通知的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 冰箱温控器数字越小制冷效果越好吗?
- 下一篇: oracle dbf 超大,oracle