2016-11-08 65 views
0

我一直在閱讀有關此問題的答案,現在已經有一段時間了,但沒有一個解決方案似乎適用於我的設置。Socket.io頁面刷新與房間斷開連接

我有一個nodeJS服務器連同express。我使用Socket.io向個人用戶發送通知。 (前端是Angular)

當用戶登錄時,他加入以他的電子郵件地址(唯一)命名的房間。

io.on('connection', function (socket) { 
    socket.on('join', function(user) { 
     //list of connected users 
     connected_users.push({socket_id: socket.id, email: user.email}); 
     socket.join(user.email); 
    }); 
    ... 

join事件從角廣播時在用戶登錄

這樣我可以通過使用電子郵件地址發送郵件,像這樣簡單地通知:

io.sockets.in(to).emit('notification', { 
    message: msg, 
    source: from, 
    destination: to, 
    event: data 
}); 

當用戶手動註銷我註冊了以下事件監聽器:

socket.on('leave', function(user) { 
    //remove the user from the list 
    var index = findUserConnected(socket.id); 
    if(index != null) { 
    connected_users.splice(index, 1); 
    } 
    socket.leave(user.email); 
}); 

socket.on('disconnect', function() { 
    //if the user refreshes the page, he is still in the connected users list 
    var email = findEmailUserConnected(socket.id); 
    if(email != null) { 
    //we make him join back his room 
    socket.join(email); 
    } 
}); 

技術上這個作品:終於有每當用戶註銷或刷新頁面是在disconnect處理程序。在頁面刷新時,用戶加入他的房間。

問題只出現在頁面刷新上,即使用戶在他的房間裏也沒有收到使用io.sockets.in(email).emit('notification', {});發送的通知。

顯然頁面刷新調用socket.disconnect(),它會生成一個新的socket_id。我不確定是否有辦法將socket_id重新分配給一個房間或類似的東西。

+0

頁面重新加載會破壞所有頁面資源,包括webSocket/socket.io連接。再次加載頁面會創建一個新的連接。您可能需要使用cookie來創建某種持久的會話ID,以便您可以識別以前的用戶並在服務器上恢復其狀態。 – jfriend00

+0

@ jfriend00「恢復其在服務器上的狀態」是什麼意思?當頁面刷新時,我已經有了socket.join,用戶被識別出來......等等。 – gyc

+0

在發生'connection'事件時,您需要能夠識別您之前配置到一個房間中的套接字並將其狀態恢復爲您想要的方式(將它放回房間中,更新'socket.id'屬於這個用戶,等等......通常,人們會使用從cookie中獲得的信息將這個新的傳入連接與您以前見過的特定用戶關聯起來 – jfriend00

回答

1

確定首先在服務器上收到'disconnect'事件意味着該套接字上的連接將要終止。所以,你現在正在做一個同樣的套接字連接回房間是沒有用的。

socket.on('disconnect', function() { 
    var email = findEmailUserConnected(socket.id); 
    if(email != null) { 
     socket.join(email); // this would never work because this socket connection is not going to exist anymore. 
    } 
}); 

我的建議是確保每次建立新連接時用戶總是重新回到房間(電子郵件)。通過在每個新連接上添加發送連接事件可以輕鬆完成。 在您的客戶端代碼做

var socket = io(); 
socket.on('connect', function() { // 'connect' event is received on client on every connection start. 
    socket.emit('join', user); // where 'user' is your object containing email. 
}) 

這樣,它確保每當建立一個新的連接聯合事件被髮送到服務器和「socket.on(」加入,...)」監聽器你的服務器將把新的套接字添加到房間中。希望這有助於:)