Vue 结合 SignalR 实现先后端实时消息同步

最近业务中须要实现服务器端与客户端的实时通讯功能,对Signalr作了一点总结和整理。javascript

SignalR 做为  ASP.NET 的一个库,可以简单方便地为应用提供实时的服务器端与客户端双向通讯功能。前端

SignalR 在客户端方面有两种API:Connections 和 Hubs。java

在特殊状况下,好比发送消息的格式是特定不变时,使用Connections API。jquery

大多数状况下使用Hubs,由于它是 Connections API 更高级的一种实现,容许客户端与服务端相互直接调用方法。一个实际应用的具体场景,好比服务端获取到新订单时,调用客户端的打印方法,客户端打印完成后,调用服务端的订单状态更新方法。webpack

下面介绍 Hubs 在前端的 APIgit

generated proxy

当使用generated proxy的时候,在语法层面上能够更加简单地调用服务端方法,就像在服务端直接调用。github

以下面是服务端的代码,表示新增一条聊天信息到列表web

public class DemoChatHub : Hub
{
    public void NewChatMessage(string name, string message) { Clients.All.addMessageToList(name, message); } }

客户端调用的时候:npm

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 时,客户端调用的时候则是element-ui

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项目里面,若是先后端分离,不会这样引用:

<script src="@Url.Content("~/signalr/hubs")" type="text/javascript"></script>

并且在客户端方法中若是要使用多个事件处理器时,不能使用generated proxy。

所以后面的例子不采起generated proxy的方式。

1.如何创建链接

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,注意调用服务器端的方法名首字母能够不大写,若是方法名称要限制必须大写,须要后端作配置。

demoChatHubProxy.invoke('newChatMessage', {name:'a',message:'b'});

3. 服务器端调用客户端方法

首先客户端要注册方法才能让服务器端调用,使用 on 方法注册。

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

plugins: [new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            'window.jQuery': 'jquery',
            'root.jQuery': 'jquery'
        })
    ]

而后在main.js中引入 SignalR

import 'signalr'

这时候就能够在Vue项目中使用SignalR了,后端的相关配置暂时略过。

新建一个signalr.js

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) =>{
        console.log('Now connected, connection ID=' + connection.id)
    }).fail(()=>{
        Message('链接失败' + error);
        console.log('Could not connect');
    })
    hub.error(function (error) {
        Message('SignalR error: ' + error);
        console.log('SignalR error: ' + error)
    })
    hub.connectionSlow(function () {
        console.log('We are currently experiencing difficulties with the connection.')
    });
    hub.disconnected(function () {
        console.log('disconnected')
    });
    return proxy
}
// 手动建立proxy
export function createHubProxy(hub){
    let proxy = hub.createHubProxy(HUBNAME)
    // 注册客户端方法
    clientMethodSets.map((item)=>{
        proxy.on(item.name,item.method)
    })
    return proxy
}

这样,在组件引入signalr.js后调用startConnection方法便可创建链接。 

了解更多 https://github.com/SignalR/SignalR

相关文章
相关标签/搜索