【问题标题】:Trouble figuring out how to return socket.join truthiness无法弄清楚如何返回 socket.join 真实性
【发布时间】:2020-06-19 19:10:27
【问题描述】:

试图找出一个可靠的方法来确认所有套接字方法成功完成。

在这种情况下,我试图添加一组房间 (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");
   });    
});

【问题讨论】:

  • 为什么要在 for 循环中解析?想想看。一个 Promise 将从“未决”转变为“已完成”或“被拒绝”一次。再次调用resolvereject 将产生零效果。
  • socket.join() 返回什么?这是一个承诺吗?
  • 这是正确的,我想我可以在 for 循环中放置一个新的承诺,然后在所有这些都完成后设置一个变量来解析。但是,是的,我不认为 socket.join() 返回一个承诺,它正在返回套接字 obj,它似乎以 Socket { .. 开始。房间键在这里就像房间:{“cTbjCBD4GpI-p0_nAAAA”:“cTbjCBD4GpI-p0_nAAAA " } 但那不是我添加的房间。这是基本功能的默认套接字空间。当我进行另一个发射以获取 convos 时,它会返回它们,但我只是想用一个发射和零 setTimouts 来做所有事情,只是承诺

标签: node.js reactjs express sockets promise


【解决方案1】:

好的,阅读 Socket.IO 文档中的here,是声明...

要离开频道,您可以调用leave,方式与join 相同。这两种方法都是异步的,并接受 callback 参数。

...这是非常重要的。

更好地解释here

因此,"joins" 可以被承诺为和 rusulting Promises 与 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");
    });    
});

这些都没有经过测试,并且涉及一些猜测。准备做一些调试。

【讨论】:

  • 感谢您向我展示了这两种方法。两种方式都有意义。这确实澄清了我对 Promise 的理解,并将有助于其余的开发。我以自己的方式实现了第一个,它按预期工作。
  • 不用担心。祝你好运。
猜你喜欢
  • 2020-12-01
  • 1970-01-01
  • 2015-04-06
  • 2014-12-18
  • 1970-01-01
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多