J'essaie de créer une API de nœud très simple à l'aide de express.js 4, mais j'ai besoin de quelques événements 'temps réel' pour lesquels j'ai ajouté socket.io. Je suis assez nouveau pour les deux, donc il me manque probablement quelque chose de fondamental, mais je ne trouve pas de bons documents/tuts à ce sujet.
Dans l'application express (créée avec le générateur express), j'ai quelque chose comme ceci basé sur des exemples simples et des documents de projet que j'ai lus. Cela fonctionne bien et depuis les applications client, je peux envoyer/recevoir les événements de socket:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use('/api', api);
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// error handlers omitted
module.exports = app;
mais je veux utiliser les sockets de mes routes API (dans le fichier ./routes/api.js dont j'ai besoin ci-dessus). Par exemple, quelqu'un peut utiliser l'API pour PUT/POST une ressource et je souhaite que cette diffusion soit transmise aux clients socket.io connectés.
Je ne vois pas comment utiliser la variable 'io' ou organiser le code actuellement dans la fonction io.sockets.on('connection' ...
dans les itinéraires express. Voici le fichier ./routes/api.js
:
var express = require('express');
var router = express.Router();
var io = ???;
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
io.sockets.emit('update', foo); // how?
});
module.exports = router;
J'ai un peu modifié vos fichiers, pouvez-vous vérifier si cela fonctionne?
Vous pouvez passer le io que vous avez défini à vos itinéraires comme ci-dessous;
require('./routes/api')(app,io);
Je n'ai pas testé les composants Socket.IO, mais il n'y a pas d'erreur de syntaxe et les routes fonctionnent également.
fichier server.js:
var express = require('express');
var app = express();
var path = require('path');
var logger = require('morgan');
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
require('./routes/api')(app,io);
console.log("Server listening at port 3000");
api.js:
module.exports = function(app,io) {
app.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
console.log("PUT OK!");
io.sockets.emit('update'); // how?
res.json({result: "update sent over IO"});
});
}
Une option consiste à le transmettre à l'objet req.
app.js:
var express = require('express');
var path = require('path');
var logger = require('morgan');
var api = require('./routes/api');
var app = express();
var io = require('socket.io').listen(app.listen(3000));
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
io.sockets.on('connection', function (socket) {
console.log('client connect');
socket.on('echo', function (data) {
io.sockets.emit('message', data);
});
});
// Make io accessible to our router
app.use(function(req,res,next){
req.io = io;
next();
});
app.use('/api', api);
// error handlers omitted
module.exports = app;
./routes/api.js:
var express = require('express');
var router = express.Router();
router.put('/foo', function(req, res) {
/*
do stuff to update the foo resource
...
*/
// now broadcast the updated foo..
req.io.sockets.emit('update', foo);
});
module.exports = router;
Une autre option consiste à utiliser req.app .
const express = require('express');
const path = require('path');
const logger = require('morgan');
const api = require('./routes/api');
const app = express();
const io = require('socket.io').listen(app.listen(3000));
// Keep the io instance
app.io = io;
app.use(logger('dev'));
app.use(express.static(path.join(__dirname, 'public')));
// ...
app.use('/api', api);
module.exports = app;
const express = require('express');
const router = express.Router();
router.put('/foo', function(req, res) {
/*
* API
*/
// Broadcast the updated foo..
req.app.io.sockets.emit('update', foo);
});
module.exports = router;
En supposant que vous souhaitiez accéder à SocketIO de n’importe où dans votre application, pas seulement dans le routeur, vous pouvez créer un singleton pour celui-ci. C'est ce qui fonctionne pour moi:
//socket-singletion.js
var socket = require('socket.io');
var SocketSingleton = (function() {
this.io = null;
this.configure = function(server) {
this.io = socket(server);
}
return this;
})();
module.exports = SocketSingleton;
Ensuite, vous devez le configurer en utilisant votre serveur:
//server config file
var SocketSingleton = require('./socket-singleton');
var http = require('http');
var server = http.createServer(app);
SocketSingleton.configure(server); // <--here
server.listen('3000');
Enfin, utilisez-le où vous voulez:
//router/index.js
var express = require('express');
var router = express.Router();
var SocketSingleton = require('../socket-singleton');
/* GET home page. */
router.get('/', function(req, res, next) {
setTimeout(function(){
SocketSingleton.io.emit('news', {msg: 'success!'});
}, 3000);
res.render('index', { title: 'Express' });
});
module.exports = router;