2015-02-02 6 views
6

Dies ist eine Frage, die andere Leute gestellt haben, aber ich kann nicht von den Antworten profitieren, die sie bekommen haben, aufgrund der verschiedenen Express-Einstellungen, die ich habe.Wie kann ich Ereignisse aus Connected Sockets mit socket.io von meinen Express 4 Routen aus ausgeben?

Ich habe socket.io implementiert und funktioniert auf einfache Weise auf meinem Server. Dies ist, wie es funktioniert:

In bin/www:

#!/usr/bin/env node 
var debug = require('debug')('gokibitz'); 
var app = require('../../server'); 

app.set('port', process.env.PORT || 3000); 

var server = app.listen(app.get('port'), function() { 
    debug('Express server listening on port ' + server.address().port); 
}); 

var io = require('socket.io').listen(server); 

io.on('connection', require('../routes/socket.js')); 

Alle meine Routen und andere Express-Setup in ../../server.js ist.

var routes = require('./server/routes/index'); 
var user = require('./server/routes/user'); 
... 

app.use('/', routes); 
app.use('/api/user/', user); 
... 
app.use('*', routes); 

Dann in ../routes/socket.js, habe ich diese vorformulierten bekam:

module.exports = function (socket) { 
    socket.emit('send:news', { hello: 'world' }); 

    setInterval(function() { 
     socket.emit('send:time', { 
      time: (new Date()).toString() 
     }); 
    }, 1000); 

    return socket; 
}; 

Dies funktioniert schön, wie ich hinzufügen möchte. Aber jetzt möchte ich in der Lage sein, Ereignisse von den verschiedenen Routen in meiner recht gewöhnlichen Express-App auszugeben, und ich kann nicht für den Rest von mir den richtigen Weg finden, einen Verweis auf das Socket-Objekt zu bekommen, das ich brauche.

Beispiel: Wenn ein Benutzer einen Kommentar abgibt, möchte ich ein Ereignis an alle verbundenen Benutzer senden, um sie über den neuen Kommentar zu informieren. Wie kann ich aus meiner routes-Datei (./server/routes/user.js) Zugriff auf das Objekt erhalten, das ich zum Ausgeben von Ereignissen benötigen?

Hier ist ein Skelett der relevanten Bits aus einer Routendatei:

var express = require('express'); 
var router = express.Router(); 

router.post('/', function (req, res) { 
    ... 
}); 

module.exports = router; 

Der einzige Ort, kann ich auf sie in der ../routes/socket.js Datei ist, die nutzlos ist.

alle Routen sind in einem app.js gesetzt, bevor Objekt jede io oder Buchse gibt es in zu übergeben.

Soll ich require('socket.io') der Lage sein, und es verwenden, irgendwie an alle angeschlossenen Steckdosen zu emittieren?

Gibt es eine vernünftige Möglichkeit, die angeschlossenen Buchsen auf ../routes/socket.js zu speichern, so dass es von anderen Routen benötigt und ausgegeben werden kann?

Kann mich jemand in die richtige Richtung lenken?

+0

Von einer Route versuchen Sie, eine Nachricht an alle verbundenen Benutzer zu senden? Oder senden Sie nur an den Benutzer, der die Anfrage auf der Route gemacht hat? Wen versuchst du von deiner Route zu senden? 'io.emit (msg, data)' sendet an alle angeschlossenen Clients. Wenn Sie dies von einem anderen Modul aus tun, müssen Sie die 'io'-Variable mit diesem anderen Modul teilen. – jfriend00

+0

Ich versuche, eine Nachricht an alle verbundenen Benutzer von einer Route aus zu senden. Beispiel: Ein Benutzer fügt einem Beitrag einen Kommentar hinzu. Ich möchte ein (namespaced) Ereignis an alle Benutzer senden, so dass jeder, der diesen Beitrag anzeigt, nach Aktualisierungen suchen kann und seine Seite mit dem neuen Kommentar aktualisiert wird. Ich weiß, ich muss das io-Objekt teilen, aber ich habe Mühe, den richtigen Weg zu finden, dies mit meinem Setup zu tun. – Nate

+0

In diesem letzten Fall müssen Sie ein Singleton erstellen, das das Objekt zurückgibt oder global erzeugt. – Exos

Antwort

13

konnte ich schließlich die Dinge bekommen mit diesem Beispiel arbeiten:

var io = require('socket.io')(); 

io.on('connection', function (socket) { 
    socket.emit('news', { hello: 'world' }); 
    socket.on('my other event', function (data) { 
    console.log(data); 
    }); 
}); 

module.exports = io; 

Dann aktualisiert ich server/bin/www dazu:

#!/usr/bin/env node 
var debug = require('debug')('gokibitz'); 
var app = require('../../server'); 
var io = require('../io'); 

app.set('port', process.env.PORT || 3000); 

var server = app.listen(app.get('port'), function() { 
    debug('Express server listening on port ' + server.address().port); 
}); 

io.attach(server); 
https://github.com/expressjs/generator/issues/45#issuecomment-53719435

ich eine neue Datei server/io.js genannt erstellt

Dann verwende ich auf meiner Route:

var io = require('../io'); 
... 
io.emit(...); 

Das fehlende Stück für mich, zumindest war die Fähigkeit, das io Objekt separat, senden Sie das richtige Objekt zu erstellen, dann io.attach(server) innerhalb bin/www verwendet es an der richtigen Stelle zu starten.

Hoffentlich hilft das jemand anderen in meine Fußstapfen treten.

var socketio = require('socket.io'); 
var io; 

module.exports = { 
socketServer: function (app) { 
    io = socketio.listen(app); 

    io.on('connection', function (socket) { 

     console.log(Object.keys(users)); 
     socket.on('message', function (data) { 
      io.emit('updateChat', 'Hello World!') 
     }); 
    }); 
    } 
} 

Und in meinem app.js:

3

Ich denke, Sie sind mit den Konzepten verwirrt. Die socket.io-Lib verwendet oder emuliert einen Websocket (bidirektionalen Socket) mit dem Client und hat keine Beziehung zu Routen.

Sie können eine Mitteilung an alle Sockets senden, um die io-Objekt:

io.emit('message_to_all', true); 

Sie auf io.sockets auf ein Array haben, mit allen Steckdosen.

Sie können verwendet Namespaces oder Zimmer, ich empfehle Sie lernen in der Dokumentation:

http://socket.io/docs/rooms-and-namespaces/#

hinzufügen etwas:

Wenn Sie eine Nachricht an alle Menschen in der gleichen senden möchten Route können Sie einem Kanal mit demselben Namen des Pfads beitreten.

Zum Beispiel in dem Client:

var socket = io(window.location.href); // Or route.. 

und den Server:

var nsp = io.of('/the/specific/route'); 
nsp.on('connection', function(socket){ 
    // ... 
}); 
nsp.emit('message_to_all_in_route', data); 

über die letzte Frage Bearbeitung:

Sie können das io-Objekt in Anfrage senden oder Antwortobjekt auf Routen mit der Express Middleware API:

Zum Beispiel:

#!/usr/bin/env node 
var debug = require('debug')('gokibitz'); 
var app = require('../../server'); 

app.set('port', process.env.PORT || 3000); 

var server = app.listen(app.get('port'), function() { 
    debug('Express server listening on port ' + server.address().port); 
}); 

var io = require('socket.io').listen(server); 

app.use(function (req, res, next) { 
    res.io = io; 
    next(); 
}); 

io.on('connection', require('../routes/socket.js')); 

Und in der Route:

route.post('/post/:id/comments', function (req, res) { 

    // Do your logic 

    var postio = res.io.of('/post/' + req.params.id); 
    postio.emit('new_comment', commentData); 

}); 
+0

Die Verwendung des 'io'-Objekts scheint einfach zu sein, aber ich weiß nicht, wie ich das 'io'-Objekt richtig teile, damit meine Routen in separaten Dateien es verwenden können. – Nate

+0

Mit den Namespaces (wie im Beispiel in meiner Antwort hinzugefügt) können Sie diese Routen mit der Methode io.of definieren. – Exos

+0

Ich denke, wir reden aneinander vorbei. Ich habe meine Frage aktualisiert, um zu verdeutlichen, wie schwierig es ist, Zugriff auf das Objekt zu erhalten, das ich für die Ausgabe von Ereignissen benötige. – Nate

1

Wie ich in meinem Kommentar sagte, können Sie an alle angeschlossenen Clients mit senden:

io.emit(msg, data); 

Dies erfordert Zugriff auf das Objekt io, das Sie in Ihrem ersten Modul erstellt haben. Der übliche Weg, das mit Ihrem Modul mit Ihrem Routen-Modul zu teilen, wäre, eine Methode aus dem Modul routes zu exportieren, mit der Sie das io Objekt übergeben können und dann, nachdem Sie das Modul angefordert und das Objekt io erstellt haben Rufen Sie einfach diese Methode auf, um das Objekt io an das Routenmodul zu übergeben und es lokal für die zukünftige Verwendung zu speichern.

io ist nur ein gemeinsames Objekt wie das Objekt app ist. Wenn ein Modul in der Lage sein soll, ein gemeinsam genutztes Objekt zu verwenden, rufen Sie in der Regel eine Methode in diesem Modul auf, um einige Objekte mit ihm zu teilen, die dann verwendet werden können.

+0

Ich fürchte, Sie überschätzen meine Fähigkeit, von Ihrem allgemeinen Rat zu profitieren. Ich habe meine Frage mit der Struktur einer meiner Routendateien aktualisiert: Wie würde ich sie ändern, um Zugriff auf das "io" -Objekt in "bin/www" zu bekommen? Ich habe versucht, 'module.export.io = io;' zu 'bin/www' und' var io = require ('../ bin/www') zu meiner Route hinzuzufügen, aber 'io' ist einfach nicht definiert. – Nate

0

Ich habe eine neue Datei sockets.js in dieser Datei gemacht

var express = require('express'); 
var app = express(); 
var http = require('http').createServer(app); 
var port = process.env.PORT || 3000; 

var io = require('./sockets').socketServer(http); 
http.listen(port, function() { 
    console.log('SERVER RUNNING.. PORT: ' + port) 
}); 

Dies ist für mich arbeiten. Viel Glück!