【问题标题】:Nodejs accessing nested variable in global scopeNodejs在全局范围内访问嵌套变量
【发布时间】:2015-02-03 22:58:45
【问题描述】:

如何根据我的以下 NodeJS 代码访问全局范围内的套接字

io.on('connection', function (socket) {
console.log('connection '+socket)
    socket.on("data",function(d){console.log('data from flash: ',d);});
    socket.emit("message","wtfwtwftwftwf hello from server");
    socket.on('disconnect', function (socket) {
        console.log("disconnect");
    });

});

我需要从以下 app.post 方法中访问套接字

var express = require('express'),
multer  = require('multer');
var app = express();

//auto save file to uploads folder
app.use(multer({ dest: './uploads/'}))

app.post('/', function (req, res) {
console.log(req.body); //contains the variables
console.log(req.files); //contains the file references
res.send('Thank you for uploading!');
});

app.listen(8080);

尚未测试,但先尝试一个简单的 getter 函数

io.on('connection', function (socket) {
    console.log('connection '+socket)
        socket.on("data",function(d){console.log('data from flash: ',d);});
        socket.emit("message","wtfwtwftwftwf hello from server");
return{
getSocket: function(){
return socket;
}
};
        socket.on('disconnect', function (socket) {
            console.log("disconnect");
        });

});

io.getSocket() ??

【问题讨论】:

  • 这几乎肯定是 X/Y 问题:您想做 X,但您询问了 Y(在全局范围内使用 socket)。 X 是什么?

标签: javascript node.js scope


【解决方案1】:

Express 的app 和 Socket.io 没有任何关系。

所以从根本上说,你不能在app.post 中使用socket

您需要识别客户。您可以使用Passport,它有一个Socket.io plugin,它基本上将app.post/getreq.user 连接到socket.request.user

注意:它不必是具有从数据库中获取的用户的经过身份验证的客户端,只需具有存储在内存中的临时用户的客户端即可。像这样的:

app.use(function(req, res, next) {
    if (!req.user) { // if a user doesn't exist, create one
        var id = crypto.randomBytes(10).toString('hex');
        var user = { id: id };
        req.logIn(user);
        res.redirect(req.lastpage || '/');
        return;
    }
    next();
});

var Users = {};
passport.serialize(function(user) {
    Users[user.id] = user;
    done(null, user);
});
passport.deserialize(function(id) {
    var user = Users[id];
    done(null, user);
});

然后您可以将客户端的套接字 ID 附加到其用户会话。

io.on('connection', function (socket) {
    socket.request.user.socketid = socket.id
});

然后在 app.post 中使用 io.emit 代替 socket.emit 使用 socketid

app.post('/', function (req, res) {
    io.to(req.user.socketid).emit('whatever');
});

注意:io.to() 用于发射到 房间,但默认情况下,每个套接字都连接到名为 socket.id 的同一个房间,因此它会起作用。

【讨论】:

  • 谢谢!!即使这是行不通的,它似乎是经过深思熟虑的,我不得不接受它是正确的;)
  • 会不会 app.post('/', function (req, res) 改成 app.post('/login', passport.authenticate('local') ?
  • @eco_bach 查看更新后的答案。不,passport.authenticate 仅用于登录/验证用户。它需要带有凭据的req.body,因此绝对不会在您的主要路线中使用它。
  • 请在下面查看我的替代答案
【解决方案2】:

Javascript 和 socketIO 专家 > 请告诉我为什么这个简单的解决方案不起作用。好像...

1 定义一个全局指针

var _this=this;

2 在我的 socketIO 处理程序中引用套接字对象

_this.socket=socket;

3 最后在 app.post 中,像这样访问套接字

_this.socket.emit(....

【讨论】:

  • socket 对象对于每个连接的客户端都是唯一的。如果将其设为全局,则全局对象将仅引用已连接的 最新 客户端的 socket 对象。你肯定不想这样。
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-13
  • 2022-01-13
  • 2017-03-05
相关资源
最近更新 更多