繁体   English   中英

javascript 文件挂起时 SignalR 连接块

[英]SignalR connect blocks while javascript file is pending

我在包含标准 google 标签管理器脚本的页面上使用 SignalR。 该脚本是异步加载的(defer=true)。

SignalR 用于可以在该页面上触发的一些长时间运行的任务,因此我禁用触发这些操作的按钮,直到 SignalR 准备就绪,即当对 connect() 的调用成功返回时。

一些客户报告说我需要很长时间才能激活按钮。 这些客户位于 google 标签管理器被阻止的公司网络上,并且由于某些原因,对 googletagmanager.com 的请求并不总是立即返回状态 403。有时它仅在超时后(例如 2 分钟后)返回 403。

我不在乎客户是否阻止了 google 标签管理器,但我的 SignalR 连接调用(在文档准备好时)将停止,直到对 google 标签管理器的调用完成。 它不应该停止,因为它们在逻辑上应该是独立的,并且脚本是用 defer=true 加载的。

我不明白为什么连接调用不会更快完成。 我发现的唯一一件事是“不要将会话状态与 SignalR 一起使用”(例如SignalR 不在服务器上使用 Session )。 我在我的 Web 应用程序中使用 Session 对象,但不是从 SignalR 中心使用。

使用 .NET Framework 4.5 和 SignalR 2.4.1

服务器上的 SignalR 启动是标准的:

using Microsoft.Owin;
using Owin;
using MyNamespace;

[assembly: OwinStartup(typeof(SignalRStartup))]
namespace MyNamespace
{
    public class SignalRStartup
    {
        public void Configuration(IAppBuilder app)
        {
            // Any connection or hub wire up and configuration should go here
            app.MapSignalR();
        }
    }
}

集线器实现对会话没有任何作用

public class CollectiefHub : Hub
{
    private static readonly IHubContext sHubContext = GlobalHost.ConnectionManager.GetHubContext<CollectiefHub>();
    public const string MsgCalcReady = "CalcReady";
    public const string MsgDocGenReady = "DocGenReady";

    public Task JoinGroup(string groupName)
    {
        return sHubContext.Groups.Add(Context.ConnectionId, groupName);
    }

    public Task LeaveGroup(string groupName)
    {
        return sHubContext.Groups.Remove(Context.ConnectionId, groupName);
    }

    private static async Task Send(string group, object msg)
    {
        await sHubContext.Clients.Group(group).receive(msg);
    }

    public static async void SendMessage(string groupName, object message)
    {
        await Send(groupName, message);
    }

    public static async void HandleListDone(string groupName, Dictionary<string, string> list)
    {
        await Send(groupName, new { list });
    }

    public static async void HandleListProgress(string groupName, string guid, int percentage)
    {
        await Send(groupName, new { guid, percentage });
    }
}

Javascript代码:

var AsyncCalc = {
    connection: $.hubConnection(),
    collectiefHub: null,
    group: window.location.pathname.split("/")[2], // Contains identifier
    calcDoneEvent: "asyncCalcDone",
    asyncObject: null,
    connected: false,

    setupSignalR: function() {
        AsyncCalc.collectiefHub = AsyncCalc.connection.createHubProxy("collectiefHub");
        AsyncCalc.collectiefHub.on("receive", function (message) {
            // Handle specific messages here
        });

        // Start connection
        AsyncCalc._start();
    },

    _start: function () {
        AsyncCalc.connection.url = "/" + window.location.pathname.split("/")[1] + "/signalr";
        AsyncCalc.connection.start().done(function () {
            AsyncCalc.connected = true;
            AsyncCalc.collectiefHub.invoke("joinGroup", AsyncCalc.group);
            $(".async").removeClass("disabled");
        });
    }
};

$(function () {
    AsyncCalc.setupSignalR();
});

Google 标签管理器只是一个包含在我页面的<head>部分中的 javascript js 文件,如下所示:

<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXX"></script>

有任何想法吗?

即使您在被阻止的脚本上使用defer属性,脚本仍必须在 DOMContentLoaded 事件触发之前尝试运行,这是 jQuery 的就绪函数等待的事件。 我不确定这是否同样适用于async属性。 你想调用AsyncCalc.setupSignalR(); 只要需要启用的按钮在页面上而不是等待 DOMContentLoaded 事件。 根据按钮的加载方式,将脚本标记移动到 HTML 正文的底部可能就足够了。 如果没有,您可以使用MutationObserver或类似的东西来等待按钮。

如果按钮异步加载,您仍然可以调用AsyncCalc.setupSignalR(); 立即运行,只等待按钮出现运行$(".async").removeClass("disabled"); .

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM