[英]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.