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

相關文章
相關標籤/搜索