我尝试了很多方法通过jQuery或JavaScript检测浏览器关闭事件。但是,不幸的是,我无法检测到关闭。 onbeforeunload 和 onunload 方法也不起作用。如何使用 SignalR 检测窗口关闭?
我想要非常精确,我想在用户最初连接到我的 MVC Razor 视图页面时触发一个事件,当他们也从页面断开连接时我也会触发一个事件(通过各种事件,比如关闭浏览器、意外关机等)。
这是我到目前为止尝试过的:
window.onbeforeunload = function (event) {
var message = 'Important: Please click on \'Save\' button to leave this page.';
if (typeof event == 'undefined')
{
event = window.event;
}
if (event)
{
event.returnValue = message;
}
return message;
};
$(function () {
$("a").not('#lnkLogOut').click(function () {
window.onbeforeunload = null;
});
$(".btn").click(function () {
window.onbeforeunload = null;
});
});
测试结果
我正在使用 asp.net core signalr,它也可能对你有用。
示例代码
"use strict";
var connection = new signalR.HubConnectionBuilder().withUrl("/mainHub")
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
this._errorState$.next(true);
return 1000;
},
reconnectDelay: 500 // set the reconnect delay to 500ms
})
.configureLogging(signalR.LogLevel.Debug).build();
connection.serverTimeoutInMilliseconds = 120000;
//Disable the send button until connection is established.
//document.getElementById("sendButton").disabled = true;
connection.on("ReceiveMessage", function (user, message) {
var li = document.createElement("li");
document.getElementById("messagesList").appendChild(li);
// We can assign user-supplied strings to an element's textContent because it
// is not interpreted as markup. If you're assigning in any other way, you
// should be aware of possible script injection concerns.
li.textContent = `${user} says ${message}`;
});
connection.start().then(function () {
console.log(connection.connectionId);
loadStatus("available");
}).catch(function (err) {
return console.error(err.toString());
});
var tryingToReconnect = false;
// Seems not work
connection.onreconnected(function () {
tryingToReconnect = false;
loadStatus("available");
return console.log("Connection Reconnected")
});
// Seems not work
connection.onreconnecting(function (err) {
tryingToReconnect = true;
return console.log(err.message)
});
async function start() {
try {
await connection.start();
loadStatus("available");
console.log("SignalR Connected.");
} catch (err) {
console.log(err);
loadStatus("connecting");
setTimeout(start, 5000);
}
};
connection.onclose((error) => {
//console.log("ConnectId" +connection.connectionId + "Disconnected");
//console.log(`Something went wrong: ${error}`);
connection.invoke("UserDisconnected");
});
// handle the beforeunload event
$(window).on('beforeunload', function () {
// your code here
console.log("Before unload event");
// notify the server that the user has disconnected
connection.invoke("UserDisconnected");
});
javascript 中的 UserDisconnected 方法。
"use strict";
//Disable the send button until connection is established.
document.getElementById("sendButton").disabled = true;
window.onload = function () {
if (connection == undefined || connection == "undefined") {
console.log("not connect to signalr server");
} else {
if (connection._connectionState == "Connected") {
document.getElementById("sendButton").disabled = false;
}
}
}
connection.on("Chat_ReceiveMessage", function (user, message) {
var li = document.createElement("li");
document.getElementById("messagesList").appendChild(li);
// We can assign user-supplied strings to an element's textContent because it
// is not interpreted as markup. If you're assigning in any other way, you
// should be aware of possible script injection concerns.
li.textContent = `${user} says ${message}`;
});
connection.on("UserDisconnected", function (user) {
var li = document.createElement("li");
document.getElementById("messagesList").appendChild(li);
// We can assign user-supplied strings to an element's textContent because it
// is not interpreted as markup. If you're assigning in any other way, you
// should be aware of possible script injection concerns.
li.textContent = `${user} says : close browser manually`;
});
document.getElementById("sendButton").addEventListener("click", function (event) {
var user = document.getElementById("userInput").value;
var message = document.getElementById("messageInput").value;
connection.invoke("Chat_SendMessageToAll", user, message).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
Hub 类中的 UserDisconnected 方法。
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Connections.Features;
using Microsoft.AspNetCore.SignalR;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace SignalRMiddleawre.Hubs
{
//[Authorize]
public partial class MainHub : Hub
{
public MainHub()
{
}
/// <summary>
/// OnConnectedAsync
/// </summary>
/// <param name="userid"></param>
/// <returns></returns>
///
public override async Task OnConnectedAsync()
{
...
await base.OnConnectedAsync();
}
/// <summary>
/// OnDisconnectedAsync
/// </summary>
/// <param name="userid"></param>
/// <returns></returns>
public override async Task OnDisconnectedAsync(Exception? exception)
{
...
await base.OnDisconnectedAsync(exception);
}
public async Task UserDisconnected()
{
// your code here
await Clients.All.SendAsync("UserDisconnected", Context.ConnectionId);
}
}
}