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


Posted in Javascript onSeptember 19, 2017

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

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

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

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

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

下面介绍 Hubs 在前端的 API

generated proxy

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

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

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

客户端调用的时候:

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

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript实现的鼠标链接提示效果生成器代码
Jun 28 Javascript
Javascript操作URL函数修改版
Nov 07 Javascript
JS两种定义方式的区别、内部原理
Nov 21 Javascript
显示今天的日期js代码(阳历和农历)
Sep 30 Javascript
JavaScript中将数组进行合并的基本方法讲解
Mar 07 Javascript
React应用中使用Bootstrap的方法
Aug 15 Javascript
JavaScript伪数组用法实例分析
Dec 22 Javascript
jQuery创建及操作xml格式数据示例
May 26 jQuery
小程序分享模块超级详解(推荐)
Apr 10 Javascript
AjaxFileUpload.js实现异步上传文件功能
Apr 19 Javascript
深度解读vue-resize的具体用法
Jul 08 Javascript
Ajax实现局部刷新的方法实例
Mar 31 Javascript
JavaScript实现的原生态兼容IE6可调可控滚动文字功能详解
Sep 19 #Javascript
vue实现页面加载动画效果
Sep 19 #Javascript
深入理解Node.js中通用基础设计模式
Sep 19 #Javascript
微信小程序媒体组件详解(视频,音乐,图片)
Sep 19 #Javascript
Javascript中将变量转换为字符串的三种方法
Sep 19 #Javascript
详解JS中的this、apply、call、bind(经典面试题)
Sep 19 #Javascript
JavaScript 中的 this 简单规则
Sep 19 #Javascript
You might like
咖啡与水的关系
2021/03/03 冲泡冲煮
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
PHP+Mysql+Ajax实现淘宝客服或阿里旺旺聊天功能(前台页面)
2017/06/16 PHP
PHP echo()函数讲解
2019/02/15 PHP
经验几则 推荐
2006/09/05 Javascript
ext实现完整的登录代码
2008/08/08 Javascript
支持ie与FireFox的剪切板操作代码
2009/09/28 Javascript
js中匿名函数的N种写法
2010/09/08 Javascript
Web跨浏览器进程通信(Web跨域)
2013/04/17 Javascript
JQuery1.8 判断元素是否绑定事件的方法
2014/07/10 Javascript
AngularJS入门教程之数据绑定原理详解
2016/11/02 Javascript
如何写好你的JavaScript【推荐】
2017/03/02 Javascript
jquery实现全选、全不选以及单选功能
2017/03/23 jQuery
原生js封装自定义滚动条
2017/03/24 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
2017/04/14 jQuery
websocket+node.js实现实时聊天系统问题咨询
2017/05/17 Javascript
基于node.js制作简单爬虫教程
2017/06/29 Javascript
详解vue axios中文文档
2017/09/12 Javascript
Vue 换肤的示例实践
2018/01/23 Javascript
JavaScript中变量提升机制示例详解
2019/12/27 Javascript
js实现简单抽奖功能
2020/11/24 Javascript
[02:41]DOTA2英雄基础教程 谜团
2013/12/10 DOTA
[01:06:42]VP vs NewBee Supermajor 胜者组 BO3 第二场 6.5
2018/06/06 DOTA
Python将xml和xsl转换为html的方法
2015/03/10 Python
Python求导数的方法
2015/05/09 Python
Python中的rfind()方法使用详解
2015/05/19 Python
Python运维开发之psutil库的使用详解
2018/10/18 Python
深入了解python中元类的相关知识
2019/08/29 Python
使paramiko库执行命令时在给定的时间强制退出功能的实现
2021/03/03 Python
Bandier官网:奢侈、时尚前卫的健身服装首选目的地
2020/07/05 全球购物
西安夏日科技有限公司Java笔试题
2013/01/11 面试题
社区工作者先进事迹
2014/01/18 职场文书
挖掘机司机岗位职责
2014/02/12 职场文书
学校拾金不昧表扬信
2015/01/16 职场文书
业务员年终工作总结2015
2015/05/28 职场文书
python获取淘宝服务器时间的代码示例
2021/04/22 Python