当我的网站在多个窗口中打开时,在实时事件中打开 window.open(使用 socket.io)

Posted

技术标签:

【中文标题】当我的网站在多个窗口中打开时,在实时事件中打开 window.open(使用 socket.io)【英文标题】:window.open on real time event (using socket.io) when my site open in more then one window 【发布时间】:2016-10-20 19:57:54 【问题描述】:

我的网站中有一个实时功能,可以打开服务器端触发的 socket.io 事件的新窗口(php/Laravel 5.1)。 问题是如果用户登录到我的网站并在多个选项卡/窗口中打开它 - 新的 window.open 多次开火,有谁知道我该如何防止它? 我的代码如下所示:

套接字监听器:

socket.on('message', function (data) 
    data = JSON.parse(data);
    if(typeof data.data !== "undefined")
        lead_data = data.data;
    else
        lead_data = data;
    
    if(typeof lead_data !== "undefined" && (lead_data.event_name == "new_call" || lead_data.event_name == "new_unsaved_call"))
        if(lead_data.user_id == uid)
            window.App.openCallWindow(data);
        
    
);

openCallWindow 函数:

openCallWindow : function(data)
    void(0);
    var lead_id = '';
    if(data && data.lead)
        lead_id = data.lead._id;
        window.open('/leads/callLead/'+lead_id,'new_lead'+Math.floor((Math.random()*999)+1), "height=800,width=1200" );
    else if(typeof data.phone !== "undefined")
        window.open('/leads/callLead/?phone='+data.phone,'new_lead'+Math.floor((Math.random()*999)+1), "height=800,width=1200" );
    else
        window.open('/leads/callLead/'+lead_id,'new_lead'+Math.floor((Math.random()*999)+1), "height=800,width=1200" );
    
,

【问题讨论】:

【参考方案1】:

客户端活动标签解决方案:

如果选项卡处于活动状态(当前已查看),您只能调用 window.open。 这可以像this:

function isTabActive()
    var state; 

    if (typeof document.hidden !== "undefined") 
        state = "visibilityState";
     else if (typeof document.mozHidden !== "undefined") 
        state = "mozVisibilityState";
     else if (typeof document.msHidden !== "undefined") 
        state = "msVisibilityState";
     else if (typeof document.webkitHidden !== "undefined") 
        state = "webkitVisibilityState";
    
    return document[state] != "hidden";

客户端使用 cookie

如果弹出窗口已经打开,您也可以使用 cookie 进行保存。 可以用js读写cookies。

使用 socket.io 的服务器端解决方案

如果您有用户帐户,请使用它们而不是 ip!否则,对于具有相同 ip 的多个用户来说,这将是错误的。

var alreadySend=;
io.on('connection', function(socket)

   if(!alreadySend.hasOwnProperty(socket.handshake.address))
   
      socket.emit("create popup", "popup1");
      alreadySend[socket.handshake.address]=true;
   
);

重置
delete alreadySend[socket.handshake.address];

另外here你可以找到更多关于通过socket.io获取ip的详细信息

【讨论】:

非常感谢您的回答,但是即使窗口不活动,我仍然需要打开新窗口。有没有办法验证我的网站打开了多少个窗口或检查事件是否已经从另一个地方触发? 我不知道这是否可能,但您可以使用 socket.io 的 ip 或用户名/用户 ID 仅将“消息”发送到每个 ip/用户的一个连接。 IP 在socket.handshake.address 中,您可以创建一个类似messageSend[ip/userName]=true/false; 的对象,然后在发送前查询此IP/用户是否已经收到消息。 我对socket.io很陌生,你能举个代码例子吗?我应该将它添加到套接字连接处理程序中吗? 我用另外两个解决方案和示例代码扩展了我的答案!【参考方案2】:

你可以使用状态并通过像

这样的函数来访问它
function isTabActive()
    var state; 

    if (typeof document.hidden !== "undefined") 
        state = "visibilityState";
     else if (typeof document.mozHidden !== "undefined") 
        state = "mozVisibilityState";
     else if (typeof document.msHidden !== "undefined") 
        state = "msVisibilityState";
     else if (typeof document.webkitHidden !== "undefined") 
        state = "webkitVisibilityState";
    
    return document[state] != "hidden";

【讨论】:

以上是关于当我的网站在多个窗口中打开时,在实时事件中打开 window.open(使用 socket.io)的主要内容,如果未能解决你的问题,请参考以下文章

当我在结构视图中保存表单然后在表单视图中打开时,它给我一个错误。每个新文件都一样

在移动浏览器中打开时反应材料 ui 没有响应

在移动设备中打开时将链接转换为幻灯片过渡

如何处理后退按钮android以退出应用程序并在首页中打开时关闭本机导航侧菜单

在 iPhone 的菜单中打开时,取消按钮无法正常运行

当文件在另一个进程中打开时,Inno Setup LoadStringFromFile 失败