2016-12-07 6 views
0

У меня следующий код работает на стороне сервера, все в порядке. Но я хочу сохранить ту же связь между вкладками n, потому что когда я открываю новую вкладку, похоже, что я отключен от первой вкладки ... Итак, как я могу поддерживать одно и то же соединение?Работа с несколькими вкладками с Socket.io

client.js

socket.emit("connected", {user: inputUser.val()}; 

app.js

var express = require("express"), 
app = express(), 
http = require("http").Server(app), 
io = require("socket.io")(http), 
users = {}; 

io.on("connection", function(socket) { 
    socket.on("connected", function(data) { 
     socket.user = data.user; 

     users[socket.user] = socket; 

     updateUsers(); 
    }); 

    function updateUsers() { 
     io.emit("users", Object.keys(users)); 
    } 

    socket.on("typing", function(data) { 
     var userMsg = data.user; 

     if(userMsg in users) { 
      users[userMsg].emit("typing", {user: socket.user}); 
     } 
    }); 

    socket.on("disconnect", function(data) { 
     if(!socket.user) { 
      return; 
     } 

     delete users[socket.user]; 

     updateUsers(); 
    }); 

}); 

var port = Number(process.env.PORT || 8000); 

http.listen(port, function() { 
    console.log("Server running on 8000!"); 
}); 

Update: typing событие выше работает отлично ... Так что я попробовал typing событие в соответствии с ответом:

var express = require("express"), 
    app = express(), 
    http = require("http").Server(app), 
    io = require("socket.io")(http), 
    users = {}; 

io.on("connection", function(socket) { 
    socket.on("connected", function(data) { 
     socket.user = data.user; 

     // add this socket to the Set of sockets for this user 
     if (!users[socket.user]) { 
      users[socket.user] = new Set(); 
     } 
     users[socket.user].add(socket); 

     updateUsers(); 
    }); 

    function updateUsers() { 
     io.emit("users", Object.keys(users)); 
    } 

    socket.on("typing", function(data) { 
     var userMsg = data.user; 

     if(userMsg in users) { 
      users[userMsg].emit("typing", {user: socket.user}); 
     } 
    }); 

    socket.on("disconnect", function(data) { 
     if(!socket.user) { 
      return; 
     } 

     // remove socket for this user 
     // and remove user if socket count hits zero 
     if (users[socket.user]) { 
      users[socket.user].delete(socket); 
      if (users[socket.user].size === 0) { 
       delete users[socket.user]; 
      } 
     } 

     updateUsers(); 
    }); 

}); 

var port = Number(process.env.PORT || 8000); 

http.listen(port, function() { 
    console.log("Server running on 8000!"); 
}); 

Но это дает следующее сообщение об ошибке:

users[userMsg].emit("typing", {user: socket.user}); ^

TypeError: users[userMsg].emit is not a function

Update²: Чтобы исправить ошибку событий typing, я просто изменил на:

socket.on("typing", function(data) { 
    var userMsg = data.user; 

    if(userMsg in users) { 
     for(let userSet of users[userMsg]) { 
      userSet.emit("typing", {user: socket.user}); 
     } 
    } 
}); 
+0

Возможный дубликат [Управление несколькими вкладками (но одним и тем же пользователем) в socket.io] (https://stackoverflow.com/questions/12166187/manage-multiple-tabs-but-same-user-in-socket-io) – StefansArya

ответ

2

Там нет простого способа разделить один сокет .io между несколькими вкладками в том же браузере. Обычная модель для нескольких вкладок будет заключаться в том, что каждая вкладка имеет свое собственное соединение socket.io.

Открытие новой вкладки и новое подключение socket.io не должны само по себе заставлять ваш сервер думать, что что-то было отключено. Если ваш код делает это, то это ошибка в коде, и, вероятно, легче исправить эту конкретную ошибку.

Фактически, если вы хотите явно поддерживать несколько вкладок и иметь возможность распознавать, что несколько вкладок могут использоваться одним и тем же пользователем, тогда вы можете изменить свой код на стороне сервера, чтобы он мог отслеживать несколько сокетов для одного пользователя, а не как он в настоящее время кодируется, чтобы отслеживать только один сокет для каждого пользователя.

Если ваш серверный код действительно просто пытается отслеживать, какие пользователи онлайн, то, вероятно, есть более простой способ сделать это, ссылаясь на подсчет каждого пользователя. Я отправлю пример кода немного.

var express = require("express"), 
app = express(), 
http = require("http").Server(app), 
io = require("socket.io")(http), 
users = {}; 

io.on("connection", function(socket) { 
    socket.on("connected", function(data) { 
     socket.user = data.user; 

     // increment reference count for this user 
     if (!users[socket.user]) { 
      users[socket.user] = 0; 
     } 
     ++users[socket.user]; 

     updateUsers(); 
    }); 

    function updateUsers() { 
     io.emit("users", Object.keys(users)); 
    } 

    socket.on("disconnect", function(data) { 
     if(!socket.user) { 
      return; 
     } 

     // decrement reference count for this user 
     // and remove user if reference count hits zero 
     if (users.hasOwnProperty(socket.user)) { 
      --users[socket.user]; 
      if (users[socket.user] === 0) { 
       delete users[socket.user]; 
      } 
     } 

     updateUsers(); 
    }); 

}); 

var port = Number(process.env.PORT || 8000); 

http.listen(port, function() { 
    console.log("Server running on 8000!"); 
}); 

Если вам нужен users объект, чтобы иметь socket объект в нем, то вы можете изменить то, что хранится в пользовательском приемлю быть Set сокетов, как это:

var express = require("express"), 
app = express(), 
http = require("http").Server(app), 
io = require("socket.io")(http), 
users = {}; 

io.on("connection", function(socket) { 
    socket.on("connected", function(data) { 
     socket.user = data.user; 

     // add this socket to the Set of sockets for this user 
     if (!users[socket.user]) { 
      users[socket.user] = new Set(); 
     } 
     users[socket.user].add(socket); 

     updateUsers(); 
    }); 

    function updateUsers() { 
     io.emit("users", Object.keys(users)); 
    } 

    socket.on("disconnect", function(data) { 
     if(!socket.user) { 
      return; 
     } 

     // remove socket for this user 
     // and remove user if socket count hits zero 
     if (users[socket.user]) { 
      users[socket.user].delete(socket); 
      if (users[socket.user].size === 0) { 
       delete users[socket.user]; 
      } 
     } 

     updateUsers(); 
    }); 

}); 

var port = Number(process.env.PORT || 8000); 

http.listen(port, function() { 
    console.log("Server running on 8000!"); 
}); 
+0

Спасибо за ответ , Я пытаюсь запустить событие «набрав», но безуспешно ... Я обновил свой код в вопросе ... Как его исправить? – Igor

+1

@Igor - Я приложил много усилий в ответ на то, что вы изначально задали, и теперь вы изменили вопрос. Пожалуйста, не делайте этого. Попробуйте поставить свой *** реальный вопрос *** в исходный вопрос, чтобы вы не меняли вещи на людей. Я предполагаю, что 'var userMsg = data.user;' вероятно, должен быть 'var userMsg = socket.user;', а затем, если вы используете 'Set' решение, вы должны изменить' users [userMsg] .emit (...) 'для итерации по множеству и отправки в каждый сокет в наборе, если вы пытаетесь отправить те же сообщения на все вкладки, открытые этим пользователем. – jfriend00

+0

Прошу прощения, я признаю, что усилия вашего ответа и насколько это хорошо, но теперь я попытался реализовать это событие, и это не сработало, поэтому я вернулся, чтобы обратиться за помощью ... – Igor

Смежные вопросы