记录生活中的点滴,分享、学习、创新
最近业务中需要实现服务器端与客户端的实时通信功能,对Signalr做了一点总结和整理。
SignalR 作为 ASP.NET 的一个库,能够简单方便地为应用提供实时的服务器端与客户端双向通信功能。
SignalR 在客户端方面有两种API:Connections 和 Hubs。
在特殊情况下,比如发送消息的格式是特定不变时,使用Connections API。
大多数情况下使用Hubs,因为它是 Connections API 更高级的一种实现,允许客户端与服务端相互直接调用方法。一个实际应用的具体场景,比如服务端获取到新订单时,调用客户端的打印方法,客户端打印完成后,调用服务端的订单状态更新方法。
下面介绍 Hubs 在前端的 API
generated proxy
当使用generated proxy的时候,在语法层面上可以更加简单地调用服务端方法,就像在服务端直接调用。
如下面是服务端的代码,表示新增一条聊天信息到列表
1 2 3 4 5 6 7 | public class DemoChatHub : Hub { public void NewChatMessage(string name, string message) { Clients.All.addMessageToList(name, message); } } |
客户端调用的时候:
1 2 3 4 5 6 7 8 9 10 | var demoChatHubProxy = $.connection.DemoChatHub; demoChatHubProxy.client.addMessageToList = function (name, message) { console.log(name + ' ' + message); }; $.connection.hub.start().done( function () { $( '#newChatMessage' ).click( function () { demoChatHubProxy.server.newChatMessage($( '#displayname' ).val(), $( '#message' ).val()); }); }); |
不使用 generated proxy 时,客户端调用的时候则是
1 2 3 4 5 6 7 8 9 10 | var connection = $.hubConnection(); var demoChatHubProxy = connection.createHubProxy( 'demoChatHub' ); demoChatHubProxy.on( 'addMessageToList' , function (name, message) { console.log(name + ' ' + message); }); connection.start().done( function () { $( '#newChatMessage' ).click( function () { demoChatHubProxy.invoke( 'newChatMessage' , $( '#displayname' ).val(), $( '#message' ).val()); }); }); |
但是在Vue项目里面,如果前后端分离,不会这样引用:
1 | <script src= "@Url.Content(" ~/signalr/hubs ")" type= "text/javascript" ></script> |
而且在客户端方法中如果要使用多个事件处理器时,不能使用generated proxy。
因此后面的例子不采取generated proxy的方式。
1.如何建立连接
1 2 3 4 5 6 7 8 | var connection = $.hubConnection( 'localhost:23123' ); //如果前后端为同一个端口,可不填参数。如果前后端分离,这里参数为服务器端的URL var demoChatHubProxy = connection.createHubProxy( 'demoChatHub' ); demoChatHubProxy.on( 'addMessageToList' , function (userName, message) { console.log(userName + ' ' + message); }); connection.start() .done( function (){ console.log( 'Now connected, connection ID=' + connection.id); }) .fail( function (){ console.log( 'Could not connect' ); }); |
需要注意的是,开始连接之前(调用 start 方法之前),最好注册至少一个事件处理方法,如果没有注册的话,Hubs的 OnConnected 方法将不会被调用,那么客户端的方法就不能被服务端调用(这容易埋坑,所以要提前注册方法)。
2.客户端如何调用服务器端方法使用 invoke,注意调用服务器端的方法名首字母可以不大写,如果方法名称要限制必须大写,需要后端做配置。
1 | demoChatHubProxy.invoke( 'newChatMessage' , {name: 'a' ,message: 'b' }); |
3. 服务器端调用客户端方法
首先客户端要注册方法才能让服务器端调用,使用 on 方法注册。
1 2 3 | demoChatHubProxy.on( 'addMessageToList' , function (userName, message) { console.log(userName + ' ' + message); }); |
4 在Vue项目中使用SignalR
首先安装 SignalR 的package,需要注意的是 SignalR 依赖 jQuery。
npm i signalr,jquery
为了方便,在webpack.base.conf.js中注册全局的jQuery
1 2 3 4 5 6 7 | plugins: [ new webpack.ProvidePlugin({ $: 'jquery' , jQuery: 'jquery' , 'window.jQuery' : 'jquery' , 'root.jQuery' : 'jquery' }) ] |
然后在main.js中引入 SignalR
import 'signalr'
这时候就可以在Vue项目中使用SignalR了,后端的相关配置暂时略过。
新建一个signalr.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | import { Message } from 'element-ui' ; const HUBNAME = 'DefaultHub' ; /*客户端调用服务器端方法*/ //更新订单打印次数 const updateOrderPrint = { name: 'updateOrderPrint' , method: function (data){ console.log(data) } } /*服务器调用客户端方法*/ // 打印新订单 const printNewOrder = { name: 'printNewOrder' , method: function (data){ console.log(data) } } const get = { name: 'Get' , method: function (data){ console.log(data) } } //服务器端的方法 const serverMethodSets = [updateOrderPrint]; //客户端的方法 const clientMethodSets = [printNewOrder,get]; //将需要注册的方法放进集合 // 建立连接 export function startConnection() { let hub = $.hubConnection(process.env.HUB_API) let proxy = createHubProxy(hub) //需要先注册方法再连接 hub.start().done((connection) =>{
*
|