尝试使用 SignalR 检测浏览器关闭事件

问题描述 投票:0回答:1

我尝试了很多方法通过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-mvc asp.net-core browser signalr real-time
1个回答
0
投票

测试结果

我正在使用 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);
        }

    }
}
© www.soinside.com 2019 - 2024. All rights reserved.