#javascript #node.js #redis #socket.io
Вопрос:
Я использую сокет.ввод-вывод вместе с redis и мне нужно получить объект сокета, так как мне нужно получить доступ к данным, добавленным во время промежуточного программного обеспечения.
Когда я это сделаю:
const { socketServer } = require('../../socket/socket');
const allSockets = await socketServer.myNamespace.adapter.sockets(new Set());
Я получаю только идентификатор сокета, а не объект сокета. Как я могу получить объект сокета?
Используя:
socket.io: 4.0.1.
socket.io-redis: 6.1.0
Обновить
const socketServer = {
_initialized: false,
_IO: null,
_myNamespace: null,
get IO() {
if (!socketServer._initialized) throw new Error('socketServer.create not called!');
return socketServer._IO;
},
get myNamespace() {
if (!socketServer._initialized) throw new Error('socketServer.create not called!');
return socketServer._myNamespace;
},
create: (server) => {
const { initMyNamespace } = require('./setupHandler');
socketServer._IO = io(server, { cors: { origin: '*' } });
const redisPort = config.get('redisPort');
const redisHost = config.get('redisHost');
const redisConnection = redisAdapter({ host: redisHost, port: redisPort });
socketServer._IO.adapter(redisConnection);
// inits
socketServer._myNamespace = socketServer._IO.of('myNamespace');
// Middlewares
socketServer._myNamespace.use(auth);
socketServer._myNamespace.on('connection', function (socket) {
initMyNamespace(socket);
});
socketServer._initialized = true;
},
};
В другом файле при вызове api:
router.post('/', async (req, res) => {
const { socketServer } = require('../../socket/socket');
let selectedSockets = [];
const allSockets = await socketServer.myNamespace.adapter.sockets(new Set());
const userCoordinates = req.body.coordinates;
for (const currentSocketObj of allSockets) {
if (isNear(userCoordinates, currentSocketObj.user.coordinates)) {
const distanceToLocation = distanceCalc(userCoordinates, currentSocketObj.user.coordinates);
currentSocketObj.distanceToLocation = distanceToLocation;
selectedSockets.push(currentSocketObj);
}
}
for (const currentSocketObj of selectedSockets) {
currentSocketObj.emit('testing123', {distance: currentSocketObj.distanceToLocation} );
}
});
Комментарии:
1. Какая версия сокета. io вы используете (некоторые изменения API в v4, вот почему я спрашиваю)?
2. @jfriend00 socket.io: 4.0.1. socket.io-redis: 6.1.0
3. Когда вы говорите, что хотите получить «объект сокета», что вы имеете в виду. Если это сервер, то в любой момент времени имеется N подключенных сокетов. Кроме того, вы используете адаптер и сокет redis. кластеризация ввода-вывода?
4. @jfriend00 Я пытаюсь получить доступ к элементу сокета, у которого есть рукопожатие. Я использую адаптер redis. Я буду использовать сокет. кластеризация ввода-вывода в будущем
5. Пожалуйста, покажите контекст кода, в котором вы пытаетесь получить доступ к сокету, потому что он, вероятно, уже находится в области as
socket
.
Ответ №1:
В socket.io v4, вы можете сделать:
// return all Socket instances
const sockets = await io.fetchSockets();
или, если у вас есть сокет, вы можете получить сокет для этого с помощью этого:
// return all Socket instances in the "room1" room of the main namespace
const sockets = await io.in(theSocketID).fetchSockets();
Оба вызова возвращают итерацию сокетов.
Если (согласно вашему комментарию) вы пытаетесь получить конкретный сокет, который находится в процессе подключения, то socket
он уже должен быть в области действия на основе обработчика событий, который вызвал вас в первую очередь. Если вы покажете этот код в контексте, мы, вероятно, сможем показать socket
, что в нем содержится ссылка.
Комментарии:
1. Могу ли я использовать
io.fetchSockets();
redis при использовании?2. @Джессика — Я верю в это, но это неправильное решение проблемы, которую вы сейчас описали. Вам просто нужно передать
socket
то, что уже было в области действия в исходном обработчике событий, в вашу функцию в другом модуле. Нет смысла использоватьfetchSockets()
для получения всего списка сокетов. Это не скажет вам, какой сокет отвечает за текущее рукопожатие. Если вы покажете нам свой код в обоих модулях, мы сможем точно помочь. Пожалуйста, перестаньте сопротивляться показу вашего фактического кода — это то, что нам нужно, чтобы помочь вам.3. Ты прав, просто не хотел усложнять вопрос… Отправил код настройки для сокета. Код, в котором я хочу получить все сокеты, содержится в запросе api. Я буду отправлять данные для каждого сокета на основе его данных внутри
4. @Jessica — Я не понимаю, на какой именно код вы хотите ссылаться
socket
изнутри и как этот код вызывается.5. @Джессика — Я не вижу в твоей настройке ничего, что было бы не так. По — моему, все в порядке. Я обычно не пытаюсь абстрагироваться и скрывать вещи, которые уже просты в использовании на объекте сервера ввода-вывода, как это делаете вы, поскольку это просто заставляет вызывающего абонента знать/изучать новый API, а не использовать полностью удовлетворительный сокет. API ввода-вывода, который уже есть, но это вопрос мнения разработчиков.