<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      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<T>,我就是為了讓前端和后端統一下。剛開始Hub<T>我糾結了好久,不知道怎么用,最后我手動做了下,認為它只是為了方便前端和后端統一。

       如果你只是簡單的繼承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<T>,自己定義一個接口,提過方法InvokeMessage供前前端調用。

          /// <summary>
          /// 客戶端js調用方法
          /// </summary>
          public interface ISingalrClient
          {
              Task InvokeMessage(Message sendMessage);
          }
          public class SingalrService : Hub<ISingalrClient>
          {
              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<SingalrService, ISingalrClient> _hubContext;
              private ISingalrSvc _singalrSvc;
              public SingalrController(IHubContext<SingalrService, ISingalrClient> hubContext, ISingalrSvc singalrSvc)
              {
                  _hubContext = hubContext;
                  _singalrSvc = singalrSvc;
              }
              /// <summary>
              /// 查詢未處理數量
              /// </summary>
              /// <param name="account"></param>
              /// <returns></returns>
              [HttpGet("{account}")]
              public async Task NewsCount(string account)
              {
                  Message sendMessage = new Message();
                  sendMessage.Data = "11";
      //剛已經講了,用戶加載首頁的時候已經把connectionid和account存入到了內存里面,現在再取用戶相關的connectionID,如果直接調用Clinets.ALL就是給所有客戶端發送消息 IReadOnlyList
      <string> connectionIds = (IReadOnlyList<string>)_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); }, }); });

        

             

       

            

      游戲也能賺錢?如果你熱愛游戲,并且想通過游戲贏得零花錢,5173是個不錯的選擇  http://www.5173.com/?recommenduserid=US15061749098191-04F6

      posted @ 2019-12-09 10:38  灬丶  閱讀(2263)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 中文字幕制服国产精品| 精品无码成人片一区二区| 亚洲人成人网站色www| 免费无码又爽又刺激高潮虎虎视频| 国产一区国产精品自拍| 国产免费福利网站| 无码人妻少妇色欲av一区二区| 日本三级香港三级人妇99| 又黄又爽又色的少妇毛片| 中文字幕乱码在线播放| 亚洲av无在线播放中文| 色爱综合激情五月激情| 国产精品无码无在线观看| 国产在线自拍一区二区三区| 无码人妻精品一区二区三区蜜桃 | 99久久精品费精品国产一区二 | 4hu44四虎www在线影院麻豆| 日日碰狠狠躁久久躁96avv| 国产真人无码作爱视频免费| 亚洲欧美综合中文| 欧洲美女黑人粗性暴交视频| 日韩精品亚洲不卡一区二区| 亚洲尤码不卡av麻豆| 野外做受三级视频| 国内精品久久久久电影院| 亚洲男女羞羞无遮挡久久丫 | 国产首页一区二区不卡| 国产精品小仙女自拍视频| 国产美女久久久亚洲综合| 国产在线观看网址不卡一区| 韩产日产国产欧产| 好吊视频一区二区三区在线| 国产日韩精品中文字幕| 日韩免费码中文在线观看| 日韩一区二区三区高清视频| 久久天堂无码av网站| 色悠悠国产在线视频一线| 好男人官网资源在线观看| 日夜啪啪一区二区三区| 欧美又黄又大又爽a片三年片| 日韩一区二区三区日韩精品|