ASP.NET SignalR Hubs API 指南 - JavaScript 客户端.md

ASP.NET SignalR Hubs API 指南 - JavaScript客户端

本文内容

  • 本主题中使用的软件版本
  • 本主题以前的版本
  • 概述
  • 生成的代理以及它为你做什么
  • 客户端设置
  • 如何建立联系
  • 如何建立跨域连接
  • 如何配置连接
  • 如何获得Hub类的代理
  • 如何在客户端上定义服务器可以调用的方法
  • 如何从客户端调用服务器方法
  • 如何处理连接生命周期事件
  • 如何处理异常
  • 如何启用客户端日志记录

警告

本文档不是最新SignalR最新版本。最新版本请见ASP.NET Core SignalR

本文介绍SignalR版本2 JavaScript客户端Hub API,例如浏览器和Windows Store (WinJS)应用程序。

SignalR Hubs API 使你能够从服务端到已连接客户端和客户端到服务端进行远程过程调用(RPCs)。在服务端代码中,定义可以被客户端调用的方法,并调用在客户端上运行的方法。在客户端代码中,定义可以被服务端调用的方法,并调用在服务端上运行的方法。SignalR为你处理所有客户端到服务端的管道。

SignalR还提供了一个持久连接的低级API。SignalR、Hub和持久连接的介绍请见Signal R 介绍

本文档使用的软件版本

文档版本

关于SignalR更早版本的信息请见SignalR旧版本

概述

本文档包含以下章节

  • 生成的代理以及它为你做什么
    • 何时使用生成的代理
  • 客户端设置
    • 如何引用动态生成的代理
    • 如何为SignalR生成的代理创建物理文件
  • 如何建立联系
    • $.connection.hub$.hubConnection()创建的对象相同
    • 异步执行start方法
  • 如何建立跨域连接
  • 如何配置连接
    • 如何指定查询字符串参数
    • 如何指定传输方法
  • 如何获取Hub类的代理
  • 如何在客户端上定义服务器可以调用的方法
  • 如何从客户端调用服务器方法
  • 如何处理连接生命周期事件
  • 如何处理异常
  • 如何启用客户端日志记录

有关如何编写服务端或.NET客户端的文档,请参阅以下参考资料:

SignalR 2 服务组件只在.NET4.5中可用(尽管在.NET4.0上有一个SignalR 2的.NET客户端)。

生成的代理以及它为你做什么

你可以编写一个JavaScript客户端来与SignalR服务端通信,或者由SignalR为你生成一个代理。代理为你简化了使用连接、编写服务端调用的方法和调用服务端方法的代码语法。

当你编写调用服务端的方法时,生成的代理使你能够使用看起来像是在执行本地函数的语法:你可以用serverMethod(arg1, arg2)替代invoke('serverMethod', arg1, arg2)。如果你写错了服务端的方法名称,生成的代理语法也可以使客户端出现直观明了的异常。如果你手动创建定义代理的文件,你还可以获得对编写调用服务器方法的代码的智能感知支持。

例如,假设你在服务端有以下的Hub类

public class ContosoChatHub:Hub
{
    public void NewContosoChatMessage(string name,string message)
    {
        Clients.All.addContosoChatMessageToPage(name,message);
    }
}

下面的代码示例演示了看起来是在服务端调用NewContosoChatMessage方法和接受来自服务端对addContosoChatMessageToPage方法调用的JavaScript代码。

使用生成的代理

var contosoChatHubProxy = $.connection.contosoChatHub;
contosoChatHubProxy.client.addContosoChatMessageToPage = function(name,message){
    console.log(name + ' ' + mesage);
}

$.connection.hub.start().done(function(){
    // 连接发送按钮来调用服务器上的NewContosoChatMessage。
    $("#newContosoChatMessage").click(function(){
        contosoChatHubProxy.server.newContosoChatMessage($("#displayname").val(),$("#message").val());
        $("#message").val('').focus();
    });
});

不使用生成的代理

var connection = $.hubConnection();
var contosoChatHubProxy = connection.createHubProxy('contosoChatHub');
contosoChatHubProxy.on('addContosoChatMessageToPage',function(name,message){
    console.log(name + ' ' + mesage);
});

$.connection.hub.start().done(function(){
    // 连接发送按钮来调用服务器上的NewContosoChatMessage。
    $("#newContosoChatMessage").click(function(){
        contosoChatHubProxy.invoke('newContosoChatMessage',$("#displayname").val(),$("#message").val());
        $("#message").val('').focus();
    });
});

何时使用生成的代理

如果你想为一个服务端调用的客户端方法注册多个事件处理程序,则不能使用生成的代理。否则,你可以根据自己的编码偏好选择是否使用生成的代理。如果你选择不使用代理,则你不必在你的客户端代码中使用script元素引用“signalr/hubs”URL。

客户端设置

JavaScript客户端需要引用jQuery和SignalR JavaScript文件。jQuery版本必须是1.6.4或以上(例如1.7.2、1.8.2或1.9.1)。如果你确定使用生成的代理,你还需要引用SignalR产生的JavaScript代理文件。下面的实例演示了在HTML页面中引用这些文件。

<script src="Scripts/jquery-1.10.2.min.js"></script>
<script src="Scripts/jquery.signalR-2.1.0.min.js"></script>
<script src="signalr/hubs"></script>

引用的顺序必须是:首先jQuery文件,然后SignalR代码、最后是SignalR代理。

如何引用动态生成的代理

在事前的实例中,引用生成的SignalR代理是动态生成的JavaScript代码,不是物理文件。SignalR动态地为代理创建JavaScript代码并提供服务,并将它发送到客户端以响应“/signalr/hub”URL。如果你在你服务端的MapSignalR方法中为SignalR连接指定了不同的URL,动态生成的代理文件的URL是你的自定义URL,后面附加了“/hub”。

备注

Windows 8(Windows Store)JavaScript客户端,使用物理代理文件而不是动态生成的代理文件。更多信息请见本文档稍后内容如何为SignalR生成的代理创建物理文件

ASP.NET MVC 4或5 Razor view 中,使用波浪符作为应用程序的根目录:

<script src="~/signalr/hubs"></script>

更多关于在MVC5中使用SignalR的信息请见开始学习SignalR和MVC 5

ASP.NET MVC3 Razor view,使用Url.Content来引用代理文件:

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

ASP.NET Web Forms 应用程序中,使用ResolveClientUrl引用或注册代理文件。它通过ScriptManager使用App根目录相对路径(以波浪号开始):

<script src='<% ResolveClientUrl("~/signalr/hubs") %>'></script>

一般情况,使用与使用CSS或JavaScript文件相同的方法指定“/signalr/hubs”URL。如果你不用波浪符指定URL,当你在Visual Studio 使用IIS Express测试时,在某些情况下你的应用程序可以正常工作,但是当你不是导IIS时就会出现404错误。更多消息请见MSDN 网站中Visual Studio中ASP.NETweb项目的web服务解析对根级资源的引用

当你在Visual Studio 2017用debug模式运行一个Web项目,而且使用的是IE浏览器,你可以在Solution Explorer 下面的 Scripts中看到代理文件。

要看文件的内容,请双击Hubs。如果你没有使用Visual Studio 2012 或 2013 和IE浏览器,或则你不在debug模式,你也可以通过浏览器访问“/signalR/hubs”URL获取到文件内容。例如,如果你的网站运行在http://localhost:56699,在你的浏览器访问http://localhost:56699/SignalR/hubs获取文件内容。

如何为SignalR生成的代理创建物理文件

作为动态生成的代理的替代方案,你可以创建一个包含代理代码的物理文件,并引用它。你可能希望通过这样来控制缓存或绑定行为,或者当你编写调用服务方法是获得智能感知。

创建代理文件需要以下步骤:

  1. 安装Microsoft.AspNet.SignalR.UtilsHuGet包

  2. 打开命令提示符并且进入到tools文件夹,它包含SignalR.exe文件。tools文件夹位于以下位置:

    [解决方案文件夹]\packages\Microsoft.AspNet.SignalR.Utils.2.1.0\tools
  3. 输入以下命令并回车

    signalr ghp /path:[包含hub类的.dll的路径]

    .dll一般在你的项目文件夹中的bin文件夹中。

    这个命令该命令在与signal .exe相同的文件夹中创建一个名为server.js的文件。

  4. 将server.js文件放在项目中适当的文件夹中,将它重命名为适当的名称,并添加一个引用来代替“signalr/hub”引用。

如何建立联系

在你可以创建连接之前,你必须创建一个链接对象、一个代理和为可从服务调用的方法注册事件处理。当代理和事件处理建立好时,通过调用start方法建立代理。

如果你使用生成的代理,你不必在你的代码中创建连接对象,因为生成的代理代码帮你创建了。

创建连接(使用生产的代理)

var contosoChatHubProxy = $.connection.contosoChatHub;
contosoChatHubProxy.client.addContosoChatMessageToPage=function(name,message){
    console.log(userName + ' ' + message);
};

$.connection.hub.start()
    .done(function(){
        console.log("连接建立成功,连接ID="+$.connection.hub.id);
    })
    .fail(function(){
        console.log("连接建立失败");
    });

创建连接(不使用生产的代理)

var connection = $.hubConnection();
var contosoChatHubProxy = connection.CreateHubProxy('contosoChatHub');
contosoChatHubProxy.on("addContosoChatMessageToPage",function(name,message){
    console.log(userName + ' ' + message);
});

connection.start()
    .done(function(){
        console.log("连接建立成功,连接ID="+$.connection.hub.id);
    })
    .failt(function(){
        console.log("连接建立失败");
    });

示例代码使用默认的“/signalr”URL去链接你的SignalR服务端。有关如何指定不同的基本URL的信息,请见ASP.NET SignalR Hubs API 指南 - 服务端 - /signalr URL

默认情况,hub的位置在当前服务端;如果你连接到不同的服务端,在调用start方法之前指定URL,如下例所示:

$.connection.hub.url="<你的后端Url>";

备注

正常情况下,在你调用start方法建立连接之前注册事件处理。如果你想在建立连接后注册一些事件处理,你可以这样做,但是在调用start方法之前,必须至少注册一个事件处理程。这样做的一个原因是应用撤销可以有多个Hub,但是你不想在只使用一个Hub时在每个Hub中触发OnConnected事件。当连接已建立,Hub代理上存在客户端方法告诉Signal触发OnConnected事件。如果你在调用start方法前没有注册任何事件处理,你可以调用Hub上的方法,但是Hub的OnConnected方法不能被调用,并且不会从服务端调用任何客户端方法。

$.connection.hub$.hubConnection()创建的对象相同

从例子中可以看出,当你使用生产的代理,$.connection.hub引用连接对象。这和当你不使用生成的代理时调用$.hubConnection()获得的对象相同。生成的代理代码通过执行以下语句为你创建连接:

// 这是生成的代理中的一行代码
signalR.hub = $.hubConnection("/signalr",{userDefaultPath : false});

当你使用生成的代理时,你可以使用$.connection.hub对连接对象做的事情与不使用生成的代理可以做事情一样。

异步执行start方法

异步执行start方法。它返回一个jQuery延迟对象,这意味着你可以为诸如pipedonefail调用方法添加回调方法。如果你有在链接连理好后想去执行的代码(例如调用服务端方法),请在回调方法中添加代码或在回调方法中调用它。.done回调方法在链接链接后执行,在服务端上的OnConnected事件处理程序方法中的任何代码完成执行之后执行。

如果将前一个示例中的“已连接”语句放在start方法调用之后的下一行代码中(不是在.done回调中),console.log行将在连接建立之前执行,如下面的示例所示:

$.connection.hub.start();
console.log("连接建立成功,连接ID="+$.connection.hub.id);

结果
结果

如何建立跨域连接

典型的代表,如果浏览器从http://contoso.com加载页面,SignalR连接在相同的域中(http://contoso.com/signalr)。如果页面从http://contoso.com连接到http://fabrikam.com/signalr,这就是跨域连接。为安全考虑,跨域连接默认是禁止的。

在SignalR 1.x 中跨域请求由单一的EnableCrossDomain标志控制。这个标志控制JSONP和CORS请求。为了较大的灵活性,已从SignalR的服务器组件中删除所有CORS支持(如果检测到浏览器支持CORS, JavaScript客户端仍然正常使用CORS),新的OWIN中间件已经支持这些场景。

如果在客户端上是JSONP请求(在旧的浏览器上支持跨域请求),需要启将在HubConfiguration对象中的EnableJSONP设置为true,如下所示。JSONP默认是禁用的,因为它不如CORS安全。

添加Microsoft.Owin.Cors 到你的项目:在包管理控制台运行下面的命令,安装该库:

Install-Package Microsoft.Owin.Cors

这个命令将添加2.1.0版本的包到你的项目中。

调用UseCors

下面代码片段演示了如何在SignalR2中实现跨域连接。

在SignalR中实现跨域请求

下面代码演示如何在SignalR2项目中启用CORS或JSONP。示例代码使用MapRunSignalR替代MapSignalR,CORS中间件只针对需要CORS支持的SignalR请求运行(而不是MapSignalR中指定的路径上的所有流量)。Map还可以用于需要为特定URL前缀(而不是整个应用程序)运行的任何其他中间件。

using Microsoft.Asp.Net.SignalR;
using Microsoft.Owin.Cors;
using Owin;
namespace MyWebApplictaion
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            // 在这里为以“/signalr”开头的请求分支管道
            app.Map("/signalr",map=>
            {
                /**
                 * SignalR之前运行设置CORS组件
                 * 默认情况下,这将允许所有的origins。你可以通过提供具有不同策略的cors选项来配置origins及http谓词。
                **/
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration{
                    /**
                     * 你可以通过取消下面的注释行来启用JSONP。
                     * JSONP请求是不安全的,单是有些旧的浏览器(和一些版本的IE)需要JSONP去执行跨域请求
                    **/
                    // EnableJSONP = true;
                };
                /**
                 * 运行SignalR管道。我们不使用MapSignalR因为这个分支已经运行在“/signalr”路径上
                **/
                map.RunSignalR(hubConfiguration);
            });
        }
    }
}

备注

  • 在你的代码中不要将jQuery.support.cors设置为true。
    示例图片
    SignalR处理CORS的使用。将jQuery.support.cors设置为true将禁用JSONP,它会导致SignalR假设浏览器支持CORS。
  • 当你连接到本地主机URL时,IE10不认为他是跨域连接,所以即使你在服务端没有启用跨域连接,应用程序也会在IE10上工作。
  • 有关IE9使用跨域连接的信息请见StackOverflow线程
  • 有关Chrome使用跨域连接的信息请见StackOverflow线程
  • 示例代码使用默认的“/signalr”URL连接到SignalR服务端。关于如何指定不同的base URL的信息,请见ASP.NET SignalR Hubs API 指南 - 服务端 - /signalr URL

如何配置连接

在建立连接之前,可以指定查询字符串参数或指定传输方法。

如何指定查询字符串参数

如果你想在客户端连接时发送数据导服务端,你可以添加查询字符串参数到连接对象。下面代码演示如何在客户端代码中设置查询字符串参数。

在调用start方法前设置查询字符串值(使用生成的代理)

$.connection.hub.qs={"version":"1.0"};

在调用start方法前设置查询字符串值(不使用生成的代理)

var connection = $.hubConneciton();
connection.qs={"version":"1.0"};

下面代码演示如何在服务端代码中读取查询字符串参数。

public class ContosoChatHub : Hub
{
    public override Task OnConnected()
    {
        var version =Context.QueryString["version"];
        if(version != "1.0")
        {
            Clients.Caller.notifyWrongVersion();
        }
        return base.OnConnected();
    }
}

如何指定传输方法

作为连接的一部分,SignalR客户端通常与服务端协商,以确定服务端和客户端都支持的最佳传输。如果你已经知道你想用的传输方式,你可以在调用start方法时避开协商过程,自己定义传输方法。

客户端指定传输方法代码(使用生成的代理)

$.connection.hub.start({transport:'longPolling'});

客户端指定传输方法代码(不使用生成的代理)

var connection = $.hubConnection();
connection.start({transport:'longPolling'});

作为一种替代方法,你可以指定多个传输方法,以你希望SignalR根据顺序尝试它们:

客户单指定应变传输方法代码(使用生成的代理)

$.connection.hub.start({transport:['webSockets', 'longPolling']});

客户单指定应变传输方法代码(不使用生成的代理)

var connection = $.hubConnection();
connection.start({transport:['webSockets', 'longPolling']});

你可以使用下面的值去指定传输方法:

  • webStockets
  • foreverFrame
  • serverSentEvents
  • longPolling

下面代码演示如何找出被连接使用的传输方法。

客户端显示被连接使用的传输方法代码(使用生成的代理)

$.connection.hub.start().done(function(){
    console.log("Connected, transport = " + $.connection.hub.transport.name);
});

客户端显示被连接使用的传输方法代码(不使用生成的代理)

var connection = $.hubConnection();
connection.hub..start().done(function(){
    console.log("Connected, transport = " + $.connection.hub.transport.name);
});

有关如何在服务端代码中检查传输方法的信息,请见ASP.NET SignalR Hubs API 指南 - 服务端 - 如何从Context属性获取客户信息。更多关于传输和应变信息,请见SignalR介绍 - Transports and Fallbacks

如何获取Hub类的代理

你创建的每个连接对象都封装了 连接到SignalR服务端的信息(包含一个或多个Hub类)。要与Hub类通信,请用你自己穿件的代理对象(如果你灭有使用产生的代理)或为你产生的代理对象。

在客户端代理名称是“骆峰式”版本的Hub类名。SignalR会自动进行此更改,以便JavaScript代码能够遵循JavaScript约定。

服务端个的Hub类

public class ContosoChatHub : Hub

获取Hub生成的客户端代理的引用

var myHubProxy = $.connection.contosoChatHub

为Hub类创建客户端代理(不使用生成的代理)

var contosoChatHubProxy = connection.createHubProxy("contosoChatHub");

如果你使用HubName属性装饰你的Hub类,请使用你指定的名称,不需要改变大小写。

服务端的Hub类使用HubName属性

[HubName("ContosoChatHub")]
public class ChatHub : Hub

获取Hub生成的客户端代理的引用

var myHubProxy = $.connection.ContosoChatHub

为Hub类创建客户端代理(不使用生成的代理)

var contosoChatHubProxy = connection.createHubProxy("ContosoChatHub");

如何在客户端上定义服务端可以调用的方法

定义服务端可以从Hub调用的方法,请使用生成的代理的client属性将事件处理到Hub代理,或如果你不使用生成的代理,请调用on方法。参数可以是复杂对象。
在调用start方法创建连接之前添加事件处理。(如果你想在调用start方法后添加事件处理,请见本文的如何创建连接,并使用所示的语法定义方法,而不使用生成的代理。)

方法名匹配不区分大小写。例如,在服务端调用Clients.All.addContosoChatMessageToPage,可以调用客户端的AddContosoChatMessageToPageaddContosoChatMessageToPage、 或addcontosochatmessagetopage方法。

在客户端定义方法(使用生成的代理)

var contosoChatHubProxy = $.connection.contosoChatHub;
contosoChatHubProxy.client.addContosoChatMessageToPage = function (userName, message) {
    console.log(userName + ' ' + message);
};
$.connection.hub.start()
    .done(function(){
        console.log('连接成功, 连接ID=' + $.connection.hub.id);
    })
    .fail(function(){
        console.log('连接失败!');
    });

在客户端替换定义的方法(使用生成的代理)

$.extend(contosoChatHubProxy.client, {
    addContosoChatMessageToPage: function(userName, message) {
    console.log(userName + ' ' + message);
    };
});

在客户端定义方法(不使用生成的代理)

var connection = $.hubConnection();
var contosoChatHubProxy = connection.createHubProxy('contosoChatHub');
contosoChatHubProxy.on('addContosoChatMessageToPage', function(userName, message) {
    console.log(userName + ' ' + message);
});
connection.start()
    .done(function(){
        console.log('连接成功, 连接ID=' + $.connection.hub.id);
    })
    .fail(function(){
        console.log('连接失败!');
    });

服务端调用客户端方法代码

public class ContosoChatHub : Hub
{
    public void NewContosoChatMessage(string name, string message)
    {
        Clients.All.addContosoChatMessageToPage(name, message);
    }
}

下面的示例包括一个作为方法参数的复杂对象。

在客户端定义获取复杂对象的方法(使用生成的代理)

var contosoChatHubProxy = $.connection.contosoChatHub;
contosoChatHubProxy.client.addMessageToPage = function (message) {
    console.log(message.UserName + ' ' + message.Message);
});

在客户端定义获取复杂对象的方法(不使用生成的代理)

var connection = $.hubConnection();
var contosoChatHubProxy = connection.createHubProxy('contosoChatHub');
chatHubProxy.on('addMessageToPage', function (message) {
    console.log(message.UserName + ' ' + message.Message);
});

服务端定义复杂对象的代码

public class ContosoChatMessage
{
    public string UserName { get; set; }
    public string Message { get; set; }
}

服务端使用复杂对象调用客户端方法的代码

public void SendMessage(string name, string message)
{
    Clients.All.addContosoChatMessageToPage(new ContosoChatMessage() { UserName = name, Message = message });
}

如何从客户端调用服务器方法

从客户端调用服务端方法,请使用生成的代理的server属性或使用Hub代理上invoke方法(如果没有使用生成的代理),返回一个复杂对象的值或参数。

Hub传入的方法名使用驼峰命名。SignalR会自动进行此更改,以便JavaScript代码能够遵循JavaScript约定。

下面代码演示如何调用服务端无返回值和有返回的方法。

未使用HubMethodName属性的服务端方法

public class contosoChatHub : Hub
{
    public void NewContosoChatMessage(ChatMessage message)
    {
        Cliens.All.addContosoChatMessageToPage(message);
    }
}

服务端传入参数的复杂对象定义代码

public class ChatMesage
{
    public string UserName{get;set;}
    public string Message{get;set;}
}

客户端调用服务端方法代码(使用生成的代理)

contosoChatHubProxy.server.newContosoChatMessage({UserName:username,Message:message})
    .done(function(){
        console.log("调用NewContosoChatMessage成功");
    })
    .fail(function(error){
        console.log("调用NewContosoChatMessage失败,异常信息:" + erroe);
    });

客户端调用服务端方法代码(不使用生成的代理)

contosoChatHubProxy.invoke('newContosoChatMessage', {UserName:username,Message:message})
    .done(function(){
        console.log("调用NewContosoChatMessage成功");
    })
    .fail(function(error){
        console.log("调用NewContosoChatMessage失败,异常信息:" + erroe);
    });

如果你使用HubMethodName属性修饰Hub方法,使用该名称时不改变大小写。

使用HubMethodName属性的服务端方法

public class ContosoChatHub : Hub
{
    [HubMethodName("NewContosoChatMessage")]
    public void NewContosoChatMessage(string name,string message)
    {
        Clients.All.addContosoChatMessageToPage(name,message);
    }
}

客户端调用服务端方法代码(使用生成的代理)

contosoChatHubProxy.server.NewContosoChatMessage(userName,message)
    .done(function(){
        console.log("调用NewContosoChatMessage成功");
    })
    .fail(function(error){
        console.log("调用NewContosoChatMessage失败,异常信息:" + erroe);
    });

客户端调用服务端方法代码(不使用生成的代理)

contosoChatHubProxy.invoke('NewContosoChatMessage', username,message)
    .done(function(){
        console.log("调用NewContosoChatMessage成功");
    })
    .fail(function(error){
        console.log("调用NewContosoChatMessage失败,异常信息:" + erroe);
    });

上面示例演示了如何调用无返回值的服务端方法。下面就演示如何调用有返回值的服务端方法。

有返回值的服务端方法代码

public class StockTickerHub : Hub
{
    public Ienumerable<Stock> GetAllStocks()
    {
        return _stockTicker.GetAllStocks();
    }
}

用于返回的Stock类

public class Stock
{
    public string Symbol{get;set;}
    public decimal Price{get;set;}
}

客户端调用服务端方法代码(使用生成的代理)

function init(){
    return stockTickerProxy.server.getAllStocks()
        .done(function(stocks){
            $.each(stocks,function(){
                var stock = this;
                console.log("Symbol=" + stock.Symbol + " Price" + stock.Price);
            });
        })
        .fail(function(error){
            console.log("Error:" + error);
        });
}

客户端调用服务端方法代码(不使用生成的代理)

function init(){
    return stockTickerProxy.invoke("getAllStocks")
        .done(function(stocks){
            $.each(stocks,function(){
                var stock = this;
                console.log("Symbol=" + stock.Symbol + " Price" + stock.Price);
            });
        })
        .fail(function(error){
            console.log("Error:" + error);
        });
}

如何处理连接生命周期事件

SignalR 提供以下连接生命周期事件供你处理:

  • starting:在通过连接发送任何数据之前触发。
  • received:在连接上接收到任何数据时触发。提供接收到的数据。
  • connectionSlow:当客户端检测到一个缓慢或频繁断开的连接时触发。
  • reconnecting:当底层传输开始重新连接时触发。
  • reconnected:当底层传输重新连接时触发。
  • stateChanged:连接状态改变时触发。提供旧状态和新状态(正在连接、已连接、开始重新连接或已断开连接)。
  • disconnected:连接断开时触发。

例如,当连接存在可能导致明显延迟的问题时,你想显示警告信息,请处理connectionSlow事件。

处理connectionSlow事件(使用生成的代理)

$.connection.hub.connectionSlow(function(){
    console.log('连接不稳定!');
});

处理connectionSlow事件(不使用生成的代理)

var connection = $.hubConnection();
connection.connectionSlow(function(){
    console.log('连接不稳定!');
});

更多信息请见在SignalR中理解和处理连接生命周期事件

如何处理异常

SignalR JavaScript客户端提供error事件供你添加处理程序。你还可以使用fail方法为服务端方法调用导致的错误添加处理程序。

如果你不在服务端明确启用明细异常信息,SignalR在发生异常后将会返回一个最简要的异常信息对象。例如,如果调用newContosoChatMessage失败,异常对象包含错误信息“There was an error invoking Hub method 'contosoChatHub.newContosoChatMessage'.”。由于安全原因在产品中发送详细异常信息到客户端是不推荐的,但是如果你为了故障诊断的想启用明细异常信息,在服务端使用下面代码:

var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR(hubConfiguration);

下面的示例显示如何为错误事件添加处理程序。

添加异常处理程序(使用生成的代理)

$.connection.hub.error(function(error){
    console.log('SignalR error:'+error);
});

添加异常处理程序(不使用生成的代理)

var connection = $.hubConnection();
connection.error(function(error){
    console.log('SignalR error:'+error);
});

下面的示例说明如何处理来自方法调用的异常。

处理来自方法调用的异常(使用生成的代理)

contosoChatHubProxy.server.newContosoChatMessage(userName,message)
    .fail(function(error){
        console.log('newContosoChatMessage error:'+error);
    });

处理来自方法调用的异常(不使用生成的代理)

contosoChatHubProxy.invoke("newContosoChatMessage",userName,message)
    .fail(function(error){
        console.log('newContosoChatMessage error:'+error);
    });

如果方法调用失败,error事件就会被触发,因此,在error方法处理程序和fail方法回调中的代码将会执行。

如何启用客户端日志记录

在连接上启用客户端日志记录,请在调用start方法建立连接前设置连接对象的logging属性。

启用日志记录(使用生成的代理)

$.connection.hub.logging = true;
$.connection.hub.start();

启用日志记录(不使用生成的代理)

var connection = $.hubConnection();
connection.logging = true;
connection.start();

打开浏览器开发工具,并记录Console标签也可以查看日志记录。逐步说明和屏幕截图文档请见服务广播与ASP.NET Signalr - 开启日志

posted @ 2020-05-26 14:32  $("#阿飞")  阅读(1056)  评论(0编辑  收藏  举报