jQuery.SignalR.js必须依赖jQuery.js,也是以jQuery插件的形式存在。

基本使用

connection连接

$.connection( url ) 创建一个新连接并返回一个 connection 对象,connection 对象下会有很多属性、事件等等,以便于我们调试、查看连接情况等等。

connection.received( handler(data) )

监听每次接收的数据,data是一JSON对象,例:

{ "A": [], "H": "msgHub", "M": "pushGet" }

其中A为所接收的数据,H为Hub名称,M为方法名称,具体使用:

$.connection.msgHub.connection.received(function (data) {
    console.log(data);
});

connection.error( handler(error) )

错误处理。

connection.stateChanged( handler(change) )

连接状态更改时发生,比如当前新连接或关闭连接时。

connection.reconnected( handler() )

重新连接。

connection.starting( handler )

在要进行 /negotiate 连接前发生,或者我们也可以说他初始完成后准备开始连接时。

connection.start()

如果单纯 start() 则会按默认来启动,并返回一个带有 promise() 的对象;也可以指定一个function做为回调。或传递一些配置参数,参数包括:

  • transport:用来指定我们采用哪一种数据传输,默认为:auto,包括:["webSockets", "foreverFrame", "serverSentEvents", "longPolling"]
  • callback:回调函数。
  • waitForPageLoad:是否等待网页完成加载后才开始连接,默认:true。

以上是比较重要的几个事件,另外还有 connection.idconnection.messageId 等属性,具体请查阅参考资料链接。

hub相关

当建立连接后,可以指定一个或多个Hub,而不管是客户端调用服务端方法或服务端调用客户端方法,我们都需要创建一个代理类对象,而这一切虽然会由SignalR来自动生成,但还是需要有所了解。

  1. 客户端调用服务端方法是执行hub对象下的 invoke 方法。对应于自动生成的Hub代理类的 server 属性。
  2. 服务端调用客户端方法是将方法绑定到 on 对象下,这样在接收数据时,只需要根据提供的JSON对象下的 H 和 M 属性就可以确认应该执行哪个函数。对应于自动生成的Hub代理类的 client 属性。

创建Hub代理

每一个Hub的类名做为客户端的代理类名,当然也可以使用 [HubName("msgHub")] 重新自定名称。相对于的客户端代码会是:

// 自动生成的引用方式
var msgHug = $.connection.msgHub;
// 或手写创建一个Hub代理对象
var msgHug = connection.createHubProxy('msgHub');

定义客户端调用服务端方法或服务端调用客户端方法

自动生成的Hub代理类

默认会根据Hub类下的公共方法自动生成一个调用服务端方法的代理脚本,可以直接引用。而对于服务端调用客户端方法的部分,依然还是需要进行手工扩展,比如:

$.extend(msgHub.client, {
    pushNow: function (res) {
        $('#J_Now').html(res);
    },
    pushGet: function (res) {
        $('#J_GetCount').html(JSON.stringify(res));
    }
});

手工创建

如前我所说的,我们只需要将我们的相应方法绑定到相应的对象中即可。比如以下是绑定供服务端调用客户端的两个方法 pushNowpushGet

msgHub.on('pushNow', function (res) {
    $('#J_Now').html(res);
});
msgHub.on('pushGet', function (res) {
    $('#J_GetCount').html(JSON.stringify(res));
});

对于客户端调用服务端方法只需要将 on 更改为 invoke 即可。

指定请求时QueryString参数

$.connection.hub.qs = {'version': '1.0' } 会将我们指定的对象转化成URL参数的形式一并发送到服务端,同时我们可以在服务端的Hub里面 Context.QueryString['version'] 接收。

解析篇

SignalR Javascript 创建两个插件,分别:$.hubConnection$.signalR

$.hubConnection:负责Hub管理,包括:注册、接收数据时的回调等等。
$.signalR:负责数据连接,比如:启动连接、发送数据、接收数据等等。

当我们创建一个 $.hubConnection 的同时也会创建一个相应的 $.signalR 并赋给 connection 属性,因此可以在一个 Hub 对象中访问,比如:msgHub.connection

当一切数据都准好后,接下来重点看一下启动时他做了些什么事:

  • 检查是否有 window.JSON 对象,如果没有我们还需要引用 json2.js,特别是IE8以下。
  • 检查 transport 配置属性值是否正确。
  • 检查当前连接状态,如果为 disconnected,更改为 connecting,此时会触发一个 changeState 事件。
  • 创建连接超时处理事件,当我们一次请求超时会尝试一次重新连接(默认超时时长是30秒)。
  • 进行一次 /negotiate 请求,用于获取连接token、服务器对webSocket的支持情况、连接超时时长等等。
  • 开始构建应该采用哪一种数据传输方式,这里有个判断就是当 /negotiateTryWebSocketsfalse 时,会将剔除webSocket连接方式。
  • 初始化完成 transport 后,会调用 start() 方法。此时会根据不同的 transport 真正的创建连接。
  • 最后会再发请求一次 /start 来检查是否创建成功。

transport

我们一直在提到数据传输,SignalR共提供四种方案,我们可以随意指定按某一种或由自动按 ["webSockets", "foreverFrame", "serverSentEvents", "longPolling"] 顺序来检测应该采用哪一种方案。

当为 auto 时会按以下规则来决定采用哪种方案:

  1. config.jsonp = true 时采用:longPolling。
  2. /negotiateTryWebSocketsfalse 剔除:webSocket。
  3. 接下按剩下的依次尝试连接。

当然我们也可以自己创建一个 transport,只需要符合规范,并把创建的挂勾到 $.signalR.transports 下。

以是基于jquery.signalR-2.1.2.js版本分析,其实整体的结构非常清晰,而且阅读起来非常简单。

参考资料

查看 SignalR系列文章