Получить объект сокета

#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 ввода-вывода, который уже есть, но это вопрос мнения разработчиков.