Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/417.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在Chrome中加载下一页之前断开websocket_Javascript_Node.js_Google Chrome_Express_Websocket - Fatal编程技术网

Javascript 如何在Chrome中加载下一页之前断开websocket

Javascript 如何在Chrome中加载下一页之前断开websocket,javascript,node.js,google-chrome,express,websocket,Javascript,Node.js,Google Chrome,Express,Websocket,在Express JS应用程序中实现基于Socket.io的通知系统时,我发现当用户浏览站点时,通过控制器加载的下一个页面在上一个页面的websocket断开事件之前进入 这是令人沮丧的,因为我正在将用户映射到套接字,并且在页面加载周期中,任何新消息都会被发送到旧套接字 我有一个检查,如果没有活动连接,它会对消息进行后台处理,然后在客户端连接时或稍后按需将消息刷新到客户端。在第二个/第三个页面控制器处理过程中,甚至在发送页面之前,当然这个过程会被愚弄到认为上一个页面的连接仍然处于活动状态。理想情

在Express JS应用程序中实现基于Socket.io的通知系统时,我发现当用户浏览站点时,通过控制器加载的下一个页面在上一个页面的websocket断开事件之前进入

这是令人沮丧的,因为我正在将用户映射到套接字,并且在页面加载周期中,任何新消息都会被发送到旧套接字

我有一个检查,如果没有活动连接,它会对消息进行后台处理,然后在客户端连接时或稍后按需将消息刷新到客户端。在第二个/第三个页面控制器处理过程中,甚至在发送页面之前,当然这个过程会被愚弄到认为上一个页面的连接仍然处于活动状态。理想情况下,我希望拆除套接字,以便在控制器运行之前删除映射条目

虽然我的应用程序太复杂,无法在这里发布,但我已在Socket.io示例应用程序中轻松重现了该问题

当在两个页面之间单击并再次返回时,将生成以下跟踪:

Page 1 controller
Page 1 done
connection  VlPV3nIQHFuzGUXKAAAU


Page 2 controller
Page 2 done
disconnecting VlPV3nIQHFuzGUXKAAAU transport close
disconnect VlPV3nIQHFuzGUXKAAAU transport close
connection  Xr7l-6TSv4VpWibXAAAV


Page 1 controller
Page 1 done
disconnecting Xr7l-6TSv4VpWibXAAAV transport close
disconnect Xr7l-6TSv4VpWibXAAAV transport close
connection  WcmYeaOnpmzYG3_qAAAW
如您所见,在页面渲染完成后,断开上一个套接字的连接

该服务器是此服务器的一个稍加修改的版本。我刚刚添加了事件日志和第二个页面来替换betwen

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var port = process.env.PORT || 3000;

app.get('/', function(req, res){
    console.log('Page 1 controller');
    res.sendFile(__dirname + '/index.html');
    console.log('Page 1 done');
});
app.get('/2', function(req, res){
    console.log('Page 2 controller');
    res.sendFile(__dirname + '/index.html');
    console.log('Page 2 done');
});

io.on('connection', function(socket){
    console.log('connection ', socket.id);
    socket.on('chat message', function(msg){
        console.log('received ', msg);
        io.emit('chat message', msg);
    });
    socket.on('disconnecting', function(reason){
        console.log('disconnecting', socket.id, reason);
    });
    socket.on('disconnect', function(reason){
        console.log('disconnect', socket.id, reason);
    });
});

http.listen(port, function(){
    console.log('listening on *:' + port);
});
我已经尝试过用setImmediate包装控制器,但是延迟不够

我猜Chrome在拆掉旧页面之前做了一些聪明的预取,或者套接字有点迟钝

如何在控制器被击中之前断开连接

编辑:在Safari中尝试会得到相同的结果,但由于它会在地址栏中预取站点,所以会得到重复的连接,这一点很复杂

Page 1 controller
Page 1 done
connection  77rWBC3fx_VrVGSsAAAj
disconnecting 77rWBC3fx_VrVGSsAAAj transport close
disconnect 77rWBC3fx_VrVGSsAAAj transport close

Page 2 controller
Page 2 done
connection  ExZeKTiG1wRix7pxAAAk
disconnecting ExZeKTiG1wRix7pxAAAk transport close
disconnect ExZeKTiG1wRix7pxAAAk transport close

Page 1 controller
Page 1 done
connection  0Xtkd5lYCyHDumHTAAAl
disconnecting 0Xtkd5lYCyHDumHTAAAl transport error
disconnect 0Xtkd5lYCyHDumHTAAAl transport error

Page 2 controller
Page 2 done
connection  0x7aV1ttnG6NT9_pAAAm

Page 2 controller
Page 2 done
disconnecting bxzFSDWGNDfEpw5MAAAi transport close
disconnect bxzFSDWGNDfEpw5MAAAi transport close
connection  l09oRFBX0-XZp658AAAn
disconnecting 0x7aV1ttnG6NT9_pAAAm transport close
disconnect 0x7aV1ttnG6NT9_pAAAm transport close
最后一个似乎是预取的。

我尝试使用window.onunload事件查看它是否运行得更早,但没有。然后我注意到window.onbeforeload事件,其中一个事件出现在下一个页面加载之前:

Page 1 controller
Page 1 done
connection  RZJ0RpDdIRM9JwcHAAAI

window_beforeunload RZJ0RpDdIRM9JwcHAAAI
Page 2 controller
Page 2 done
window_unload RZJ0RpDdIRM9JwcHAAAI
disconnecting RZJ0RpDdIRM9JwcHAAAI transport close
disconnect RZJ0RpDdIRM9JwcHAAAI transport close
connection  5wU3WklUptDVm7HHAAAJ

window_beforeunload 5wU3WklUptDVm7HHAAAJ
Page 1 controller
Page 1 done
window_unload 5wU3WklUptDVm7HHAAAJ
disconnecting 5wU3WklUptDVm7HHAAAJ transport close
disconnect 5wU3WklUptDVm7HHAAAJ transport close
connection  VOywtaf_4nAipPpvAAAK
与此修改后的客户:

      window.onbeforeunload = function(){
          socket.emit('window_beforeunload');
      };
      window.onunload = function(){
          socket.emit('window_unload');
      };
这台服务器:

io.on('connection', function(socket){
    ...

    socket.on('window_beforeunload', function(){
        console.log('window_beforeunload', socket.id);
    });
    socket.on('window_unload', function(){
        console.log('window_unload', socket.id );
    });
});

您应该只移动到不改变的标识符,而不是物理socketsYes,这就是我正在做的,但是我必须在连接期间将标识符映射到sockets id,并使用每个用户的视图中烘焙的连接参数令牌。否则,我如何通过另一个标识符向特定客户发送消息?我想这是另一个问题,也许我会单独发布。我现在已经解决了这个具体问题。但是我有兴趣不去解决它!