使用 Express 4 模块化 Socket.io
Modularizing Socket.io with Express 4
我正在尝试模块化我的应用程序文件,但我遇到了 Socket.io 的问题。我想在 routes.js
中使用 io。像这样:
var router = require('express').Router();
var io = require('./sockets/my-io');
router.get('/', function(req, res) {
io.emit('request-detected');
});
module.exports = router;
但我做不到,因为 socket.io 需要应用程序服务器,而当我在 routes.js 文件中时,应用程序服务器尚未侦听或正在导出。
你能给我一个解决方案,或者任何其他解决这个问题的方法吗?
这是我所拥有的,如果可能的话,我想保留文件结构:
app.js
var app = require('express')();
var routes = require('./routes');
/* ... */
app.use('/contacts', routes);
module.exports = app;
bin/www
#!/usr/bin/env node
var app = require('../wallet');
var server = app.listen(port, function() {
debug('Express is listening o port ' + port);
});
routes.js
var router = require('express').Router();
router.get('/', function(req, res) {
console.log('hey');
});
module.exports = router;
如果我对你的问题理解正确,也许你可以试试这个方法。
在您的 routes.js
文件中
var app = require('./app');
var server = require('http').createServer(app);
var io = require('./sockets/my-io')(server);
var route = app.Router();
在您的 app.js
文件中
var port = process.env.PORT || 3000;
app.listen(port,function(){
console.log('server on port ' + port)
})
您可以通过将 io 变量传递给您的路由模块来实现。
bin/www
#!/usr/bin/env node
var app = require('./app');
var server = app.listen(3000, function() {
console.log('Express is listening on port 3000');
}); // start the server
var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes
app.use('/', routes);
app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');
module.exports = app;
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newEvent', function (data) {
console.log(data);
});
});
return io;
}
module.exports = init;
routes.js
var express = require('express');
var route = express.Router();
function init(io) {
route.get('/', function (req, res) {
res.render('index.ejs', {});
setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
});
return route;
}
module.exports = init;
上面的代码对我有用。但是,我不确定你为什么要这样做。
在路由器内部,您仍然可以完全控制要通过 html 发送给用户的内容,因此您可以直接将数据添加到 html。
socket.io 的想法是,一旦客户端加载了 html 并使用 socket.io.
与您的服务器建立了连接,您就可以在客户端之间发送数据。
正如您在 routes.js
中看到的那样,我必须向发射添加超时。这是因为套接字事件将在浏览器重新加载页面之前发出。在我的例子中,浏览器记录了事件,然后立即刷新,丢失了你刚刚发送的数据。
另一个问题是您对请求页面的客户端的套接字一无所知,因为他还没有连接。这意味着调用 io.emit()
会将事件发送到所有连接的套接字。
就像我说的,这真的取决于你到底想做什么。
编辑:
您可以使用 socket.io 来更新您的联系人,而不是使用 ajax。
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newContact', function (data, callback) {
// add data.contactName to db
// after adding something, you use the callback to
// send the added data back to the client
// callback(newContact);
});
});
return io;
}
module.exports = init;
index.html
<script type="text/javascript" >
var socket = io();
// call this emit when the user wants to add a contact
socket.emit('newContact', {contactName: name}, function(newContact) {
// here you will get the result from the server and you can
// update the html with jquery for example
});
</script>
我正在尝试模块化我的应用程序文件,但我遇到了 Socket.io 的问题。我想在 routes.js
中使用 io。像这样:
var router = require('express').Router();
var io = require('./sockets/my-io');
router.get('/', function(req, res) {
io.emit('request-detected');
});
module.exports = router;
但我做不到,因为 socket.io 需要应用程序服务器,而当我在 routes.js 文件中时,应用程序服务器尚未侦听或正在导出。
你能给我一个解决方案,或者任何其他解决这个问题的方法吗?
这是我所拥有的,如果可能的话,我想保留文件结构:
app.js
var app = require('express')();
var routes = require('./routes');
/* ... */
app.use('/contacts', routes);
module.exports = app;
bin/www
#!/usr/bin/env node
var app = require('../wallet');
var server = app.listen(port, function() {
debug('Express is listening o port ' + port);
});
routes.js
var router = require('express').Router();
router.get('/', function(req, res) {
console.log('hey');
});
module.exports = router;
如果我对你的问题理解正确,也许你可以试试这个方法。
在您的 routes.js
文件中
var app = require('./app');
var server = require('http').createServer(app);
var io = require('./sockets/my-io')(server);
var route = app.Router();
在您的 app.js
文件中
var port = process.env.PORT || 3000;
app.listen(port,function(){
console.log('server on port ' + port)
})
您可以通过将 io 变量传递给您的路由模块来实现。
bin/www
#!/usr/bin/env node
var app = require('./app');
var server = app.listen(3000, function() {
console.log('Express is listening on port 3000');
}); // start the server
var socket = require('./socket')(server); // require socket.io code
var routes = require('./routes')(socket); // require routes
app.use('/', routes);
app.js
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.set('views engine', 'ejs');
app.set('views', __dirname + '/');
module.exports = app;
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newEvent', function (data) {
console.log(data);
});
});
return io;
}
module.exports = init;
routes.js
var express = require('express');
var route = express.Router();
function init(io) {
route.get('/', function (req, res) {
res.render('index.ejs', {});
setTimeout(function() {io.emit('newEvent', {message: "Hi from the server"})}, 2000);
});
return route;
}
module.exports = init;
上面的代码对我有用。但是,我不确定你为什么要这样做。
在路由器内部,您仍然可以完全控制要通过 html 发送给用户的内容,因此您可以直接将数据添加到 html。 socket.io 的想法是,一旦客户端加载了 html 并使用 socket.io.
与您的服务器建立了连接,您就可以在客户端之间发送数据。正如您在 routes.js
中看到的那样,我必须向发射添加超时。这是因为套接字事件将在浏览器重新加载页面之前发出。在我的例子中,浏览器记录了事件,然后立即刷新,丢失了你刚刚发送的数据。
另一个问题是您对请求页面的客户端的套接字一无所知,因为他还没有连接。这意味着调用 io.emit()
会将事件发送到所有连接的套接字。
就像我说的,这真的取决于你到底想做什么。
编辑:
您可以使用 socket.io 来更新您的联系人,而不是使用 ajax。
socket.js
var socketio = require('socket.io');
function init(server) {
var io = socketio(server);
io.on('connection', function (socket) {
console.log("socket connected");
socket.on('newContact', function (data, callback) {
// add data.contactName to db
// after adding something, you use the callback to
// send the added data back to the client
// callback(newContact);
});
});
return io;
}
module.exports = init;
index.html
<script type="text/javascript" >
var socket = io();
// call this emit when the user wants to add a contact
socket.emit('newContact', {contactName: name}, function(newContact) {
// here you will get the result from the server and you can
// update the html with jquery for example
});
</script>