Nodejs聊天室例子代码,运行出错,TypeError: Object #<Socket> has no method 'set'

Nodejs聊天室例子代码,运行出错,TypeError: Object #<Socket> has no method 'set’

var httpd = require(‘http’).createServer(handler); var io = require(‘socket.io’).listen(httpd); var fs = require(‘fs’);

httpd.listen(4000);

function handler(req,res){ fs.readFile(__dirname + ‘/index.html’, function(err,data){ if(err){ res.writeHead(500); return res.end(‘错误读取index.html文件’); } res.writeHead(200); res.end(data); }); }

io.sockets.on(‘connection’,function(socket){ socket.on(‘clientMessage’,function(content){ socket.emit(‘serverMessage’,'You said: ’ + content); socket.get(‘username’,function(err,username){ if(! username){ username = socket.id; } socket.broadcast.emit(‘serverMessage’,username + ’ said: ’ + content); }); });

socket.on('login',function(username){
    socket.set('username',username,function(err){
        if(err) { throw err;}
        socket.emit('serverMessage','Currently logged in as ' + username);
        socket.broadcast.emit('serverMessage','User ' +  username + 'logged in');
    });
});

socket.emit(‘login’);

});

以上代码可运行,一旦输入用户名提示TypeError: Object #<Socket> has no method 'set’报错退出,请问是神马原因?


4 回复

你遇到的错误 TypeError: Object #<Socket> has no method 'set' 是因为 socket.setsocket.get 方法在较新版本的 Socket.IO 中已经被移除。Socket.IO 的 API 发生了一些变化,新的版本使用不同的方法来设置和获取数据。

下面是修改后的代码示例:

var httpd = require('http').createServer(handler);
var io = require('socket.io').listen(httpd);
var fs = require('fs');

httpd.listen(4000);

function handler(req, res) {
    fs.readFile(__dirname + '/index.html',
        function (err, data) {
            if (err) {
                res.writeHead(500);
                return res.end('错误读取index.html文件');
            }
            res.writeHead(200);
            res.end(data);
        });
}

io.sockets.on('connection', function (socket) {
    socket.on('clientMessage', function (content) {
        socket.emit('serverMessage', 'You said: ' + content);
        socket.username = socket.username || socket.id;
        socket.broadcast.emit('serverMessage', socket.username + ' said: ' + content);
    });

    socket.on('login', function (username) {
        socket.username = username;
        socket.emit('serverMessage', 'Currently logged in as ' + username);
        socket.broadcast.emit('serverMessage', 'User ' + username + ' logged in');
    });

    socket.emit('login');
});

解释

  1. 删除 socket.setsocket.get

    • 在新的 Socket.IO 版本中,不再有 socket.setsocket.get 方法。
    • 取而代之的是直接使用 JavaScript 对象属性来存储和检索数据。例如,将用户名存储为 socket.username
  2. 更新登录逻辑

    • 当用户登录时,将用户名存储在 socket.username 属性中,而不是使用 socket.set
    • 这样可以在后续的消息处理中轻松访问用户名。
  3. 广播消息

    • 使用 socket.broadcast.emit 来向其他客户端发送消息。

通过这些修改,你的聊天室代码应该可以正常运行,不会再出现 TypeError 错误。


socket.io中的get / set方法在新版本中已经被抛弃了,官方文档中有说的 http://socket.io/docs/migrating-from-0-9/

那用什么方法代替了呢?

你遇到的 TypeError: Object #<Socket> has no method 'set' 错误是因为 socket.setsocket.get 方法在较新的 Socket.IO 版本中已被移除。Socket.IO 从 v1.0 开始采用不同的方式来存储和检索用户数据。

你可以使用 socket.handshake.query 或者将数据存储在服务器端的数据结构(如一个全局对象)中来代替。

以下是如何修改你的代码以适应 Socket.IO v4.x 的示例:

const http = require('http').createServer(handler);
const io = require('socket.io')(http);
const fs = require('fs');

http.listen(4000);

function handler(req, res) {
    fs.readFile(__dirname + '/index.html', (err, data) => {
        if (err) {
            res.writeHead(500);
            return res.end('错误读取index.html文件');
        }
        res.writeHead(200);
        res.end(data);
    });
}

let users = {};

io.on('connection', (socket) => {
    socket.on('clientMessage', (content) => {
        const username = users[socket.id] || socket.id;
        socket.emit('serverMessage', 'You said: ' + content);
        socket.broadcast.emit('serverMessage', username + ' said: ' + content);
    });

    socket.on('login', (username) => {
        users[socket.id] = username;
        socket.emit('serverMessage', 'Currently logged in as ' + username);
        socket.broadcast.emit('serverMessage', 'User ' + username + ' logged in');
    });

    // 示例登录事件触发
    socket.emit('login');
});

在这个修改后的版本中,我使用了一个名为 users 的全局对象来存储每个连接用户的用户名。这样可以避免使用已弃用的 socket.setsocket.get 方法。当接收到客户端的消息时,我们检查 users 对象中的用户名,并将其发送给其他客户端。

回到顶部