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 相关文章推荐
Prototype ObjectRange对象学习
Jul 19 Javascript
JavaScript中null与undefined分析
Jul 25 Javascript
JSON.parse()和JSON.stringify()使用介绍
Jun 20 Javascript
js实现二代身份证号码验证详解
Nov 20 Javascript
JavaScript和CSS交互的方法汇总
Dec 02 Javascript
jQuery Mobile页面返回不需要重新get
Apr 26 Javascript
Jquery组件easyUi实现选项卡切换示例
Aug 23 Javascript
javaScript中定义类或对象的五种方式总结
Dec 04 Javascript
微信小程序富文本渲染引擎的详解
Sep 30 Javascript
详解vue项目打包后通过百度的BAE发布到网上的流程
Mar 05 Javascript
Vue.js项目中管理每个页面的头部标签的两种方法
Jun 25 Javascript
Vue组件通信的几种实现方法
Apr 25 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
php桌面中心(三) 修改数据库
2007/03/11 PHP
一个PHP的远程图片抓取函数分享
2013/09/25 PHP
PHP正则表达式替换站点关键字链接后空白的解决方法
2014/09/16 PHP
摘自织梦CMS的HTTP文件下载类
2015/08/08 PHP
ThinkPHP模板标签eq if 中区分0,null,false的方法
2017/03/24 PHP
showModelessDialog()使用详解
2006/09/21 Javascript
日期 时间js控件
2009/05/07 Javascript
js跨域和ajax 跨域问题的实现思路
2009/09/05 Javascript
关于Javascript作用域链的八点总结
2013/12/06 Javascript
jquery动态添加删除一行数据示例
2014/06/12 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
webpack 2的react开发配置实例代码
2017/07/28 Javascript
详解用node搭建简单的静态资源管理器
2017/08/09 Javascript
javaScript canvas实现(画笔大小 颜色 橡皮的实例)
2017/11/28 Javascript
angular2路由之routerLinkActive指令【推荐】
2018/05/30 Javascript
微信小程序实现弹出菜单功能
2018/06/12 Javascript
React SSR样式及SEO的实践
2018/10/22 Javascript
Javascript实现动态时钟效果
2018/11/17 Javascript
Vue源码解析之数组变异的实现
2018/12/04 Javascript
js实现带积分弹球小游戏
2020/07/21 Javascript
Python实现测试磁盘性能的方法
2015/03/12 Python
在Django中创建URLconf相关的通用视图的方法
2015/07/20 Python
浅谈python jieba分词模块的基本用法
2017/11/09 Python
Python 3.x 判断 dict 是否包含某键值的实例讲解
2018/07/06 Python
解决安装新版PyQt5、PyQT5-tool后打不开并Designer.exe提示no Qt platform plugin的问题
2020/04/24 Python
英国奢华护肤、美容和Spa品牌:Temple Spa
2019/11/02 全球购物
中软Java笔试题
2012/11/11 面试题
25岁生日感言
2014/01/13 职场文书
公司端午节活动方案
2014/02/04 职场文书
初中同学会活动方案
2014/08/22 职场文书
2014最新房贷收入证明范本
2014/09/12 职场文书
安全生产标语大全
2014/10/06 职场文书
国王的演讲观后感
2015/06/03 职场文书
2016机关干部作风建设心得体会
2016/01/21 职场文书
详解Golang如何优雅的终止一个服务
2022/03/21 Golang
面试官问我Mysql的存储引擎了解多少
2022/08/05 MySQL