Проблема в том, чтобы выяснить, как вернуть socket.join правдивости - PullRequest
0 голосов
/ 07 марта 2020

Попытка найти верный путь для подтверждения успешного завершения всех методов сокетов.

В этом случае я пытаюсь добавить массив комнат (socket.join (roomname)); в сокет и затем подтвердите, что все они были добавлены, но я не могу найти способ запустить console.log (socket.rooms); после того, как это было установлено. Он всегда печатает комнату по умолчанию, а другие комнаты я вижу только после того, как я снова избыточно излучаю из клиента.

Я действительно пытаюсь избежать использования setTimeout или чека с setInterval и просто пытаюсь увидеть как я могу дать обещание, чтобы розетка была соединена с каждой комнатой. В настоящее время консольный журнал регистрирует только весь сокет. У кого-нибудь есть опыт с этим?

io.on("connection", socket => {
    console.log("New client connected");
    socket.on('fetchConvos', async function(rooms) {
        let roomsString;
        let result = await mapper(rooms); // makes into array
        let joinRooms = new Promise((resolve, reject) => { // Promise to add client to all rooms
            for (let i = 0; i < result.length; i++) {
                resolve(socket.join(result[i]));
            }
            throw new Error();
        })
        // Complete putting user in an array of rooms and then print confirmation that rooms were added
        joinRooms.then(() => {
            console.log(socket.rooms);
            result.forEach((string, index) => {
                if (string) {
                    roomsString += string + ", ";
                }
            });
            socket.emit("chat", "You are now in these rooms: " + roomsString); // emit back to socket 
        }).catch(error => console.log(error));  
   })
   socket.on("disconnect", () => {
        console.log("Client disconnected");
   });    
});

1 Ответ

0 голосов
/ 08 марта 2020

ОК, чтение здесь в документации Socket.IO - это утверждение ...

Чтобы выйти из канала, вы вызываете leave так же, как join. Оба метода являются асинхронными и принимают аргумент callback.

..., что очень важно.

Лучше объяснено здесь .

Таким образом, "соединения" могут быть обещаны, а rusulting обещания агрегированы с Promise.all().

io.on('connection', socket => {
    console.log('New client connected');
    socket.on('fetchConvos', async function(rooms) {
        try {
            let results = await mapper(rooms); // array
            // first, map results to array of Promises, where each Promise represents a socket.join() operation.
            let promises = results.map(room => {
                // here, promisify socket.join() on-the-fly and return Promise
                return new Promise((resolve, reject) => {
                    socket.join(room, (err) => {
                        if(err) reject(err);
                        else resolve(room);
                    });
                });
            });

            // Here, you probably want any failures of socket.join() not to scupper promise aggregation with Promise.all();
            // see https://stackoverflow.com/a/31424853/3478010
            const reflect = p => p.then(v => ({v, status: "fulfilled" }),
                            e => ({e, status: "rejected" }));

            let rooms = (await Promise.all(promises.map(reflect))).filter(o => o.status !== 'rejected').map(o => o.v);
            let rooms_ = Object.keys(socket.rooms); // from documentation

            // rooms and rooms_ should be similar, maybe the same ???
            console.log(rooms);
            console.log(rooms_);

            // now, map rooms, or rooms_, to whatever you wish to emit to `chat`, eg ...
            let roomsString = rooms.join(', '); // .join() here is the Array method Array.prototype.join()
            socket.emit('chat', `You are now in these rooms: ${roomsString}`); // emit to `chat`

            // Based on example in the documentation, you can also broadcast to to everyone in each room joined, eg ...
            rooms_.forEach(room => {
                io.to(room).emit('a new user has joined the room'); // broadcast
            });
        }
        catch(error) {
            console.log(error);
            socket.emit('chat', error.message); // for debugging
        }
    });
    socket.on("disconnect", () => {
        console.log("Client disconnected");
    });    
});

В качестве альтернативы socket.join() также принимает массив комнат, что упрощает задачу:

io.on('connection', socket => {
    console.log('New client connected');
    socket.on('fetchConvos', async function(rooms) {
        try {
            let results = await mapper(rooms); // array
            // promisifying socket.join() allows `await` to be used (and avoids nesting).
            await new Promise((resolve, reject) => {
                socket.join(rooms, (err) => {
                    if(err) reject(err);
                    else resolve();
                });
            });

            let rooms_ = Object.keys(socket.rooms); // from documentation

            // rooms and rooms_ should be similar, maybe the same ???
            console.log(rooms);
            console.log(rooms_);

            // now, from rooms, or rooms_, compose whatever you wish to emit to `chat`, eg ...
            let roomsString = rooms.join(', '); // .join() here is the Array method Array.prototype.join()
            socket.emit('chat', `You are now in these rooms: ${roomsString}`); // emit to `chat`

            // Based on example in the documentation, you can also broadcast to to everyone in each room joined.
            rooms.forEach(room => {
                io.to(room).emit('a new user has joined the room'); // broadcast
            });
        }
        catch(error) {
            console.log(error);
            socket.emit('chat', error.message); // for debugging
        }
    });
    socket.on("disconnect", () => {
        console.log("Client disconnected");
    });    
});

Ничего из этого не проверено, и есть некоторые догадки. Будьте готовы сделать некоторую отладку.

...