2016-05-20 4 views
2

Bitte entschuldigen Sie alle noobiness, ich lerne. :)Wie wird Socket.IO in Node.JS ordnungsgemäß für die Verwendung in Routen/mit Heroku verwendet?

Ich habe Socket.IO eingerichtet, so dass ich io.sockets.emit innerhalb meiner Routen verwenden kann, und ich habe das funktioniert. Es gibt ein paar Probleme.

  1. (GELöST? SEE EDIT 3) nutzen zu können, kann ich nicht mit dem Wort socket starten. Ich muss mit io beginnen oder ich bekomme "ReferenceError: Socket ist nicht definiert." Ich würde gerne socket.broadcast.emit verwenden können, um das Ereignis an alle Clients mit Ausnahme des aktuellen Benutzers zu senden. Im Moment muss ich auf der Client-Seite überprüfen, ob das Ereignis ausgeführt wird, wenn es der aktuelle Benutzer ist, und es wird zu einem echten Problem, da ich während des Projektfortschritts mehr Ereignisse ausgeben muss.

  2. (GELÖST, SEE EDIT 1 & 2) Ich habe die Anwendung mit node app.js und starten Sie den Server jedes Mal manuell I eine serverseitige Änderung vornehmen laufen. Wenn ich nodemon ausführen, bekomme ich "Port 3000 wird bereits verwendet." Ich glaube, dass dies auf die folgende Beziehung gesetzt werden müssen ...

  3. (GELÖST, SEE EDIT 2) Wann Heroku schieben, ich habe den Port aus dem Code unter 3000-80 in bin/www geändert und app.js, aber es funktioniert nicht (ich kann einen Fehler 404 für Sockets in der Konsole sehen). Wenn dies und # 2 durch den Umgang mit http/Ports an beiden Orten verursacht werden, wie kann ich dies richtig einrichten und warum funktioniert node app.js?

  4. Ich muss Socket.IO nur auf der unten gezeigten Route (Schlachtfeld) ausführen. Tue ich das schon mit mache ich das schon mit require('./routes/battlefield')(io)?

bin/www

var app = require('../app'); 
var port = normalizePort(process.env.PORT || '3000'); 
app.set('port', port); 
var server = http.createServer(app); 
server.listen(port); 

app.js

var app = express(); 
var http = require('http').Server(app); 
http.listen(3000); 
var io = require('socket.io')(http); 

app.set('socketio', io); 
var battlefield = require('./routes/battlefield')(io); 

battlefield.js

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

var returnRouter = function(io) { 
    router.get('/', function(req, res, next) { 
    // other stuff 
    io.sockets.emit('message', 'This works'); 
    socket.broadcast.emit('message', 'Socket is undefined'); 
    }) 
    return router; 
}; 
module.exports = returnRouter; 

Ich habe versucht, meine Routen in io.on('connection', function (socket) { Einwickeln der Lage sein, socket zu verwenden und statt 'Socket ist nicht definiert', das Ereignis tritt nicht auf.

var returnRouter = function(io) { 
    io.on('connection', function (socket) { 
    router.get('/', function(req, res, next) { 
     // other stuff 
     socket.emit('message', 'This is never emitted'); 
    }) 
    }) 
    return router; 
}; 

Ich entschuldige mich für so eine lange Frage. DANKE für jede Hilfe!


EDIT1: diese Frage Schreiben aus mir geholfen, das Problem besser zu verstehen. Ich habe server.listen(port); in meinem bin/www auskommentiert und nodemon funktioniert jetzt. Allerdings stürzt die App auf Heroku ab. Mein Procfile ist web: node ./bin/www ... muss das geändert werden?

EDIT2: Nach herauszufinden Edit1 und ein bisschen googeln, fand ich, dass ich nicht server.listen(); (bin/www) undhttp.listen(3000); (app.js) haben kann.

In bin/www, entfernte ich server.listen();.

In app.js, habe ich aus Gründen der Übersichtlichkeit var http = ... zu var server = ... geändert und habe für process.env.PORT || '3000';, aus bin/www. Ich habe auch app.set('socketio', io); entfernt, weil es so aussieht, als würde es nichts tun ... Ich frage mich, warum es da drin war.

app.js

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

var server = require('http').Server(app); 
var io = require('socket.io')(server); 
var port = process.env.PORT || '3000'; 
server.listen(port); 

Dies macht auch Heroku Arbeit wegen process.env.PORT, hurra! Ich denke, node app.js funktioniert, weil ich die App mit app.js initialisiert habe, ich denke, bin/www wird nicht ausgeführt, wenn Sie das tun?

Ich brauche immer noch Hilfe mit # 1 (mit socket.broadcast.emit).

EDIT 3: Nun, es dauerte buchstäblich den ganzen Tag, aber ich glaube, ich habe es mit einer Eigenart herausgefunden. Natürlich konnte ich socket nicht verwenden, es ist ein Parameter, der beim Verbinden gegeben wird. Ich muss auch über verschiedene Routen Socket zugreifen und gefunden this SO question. Dies ist, was ich am Ende in battlefield.js tun:

var returnRouter = function(io) { 
    var socket; 
    router.get('/', authenticatedUser, function(req, res, next) { 
    io.on('connection', function(client){ 
     socket = client; 
    }); 

    // other stuff 
    res.render('battlefield', {/* data */}); 
    setTimeout(function(){socket.emit('test', 'It works!')}, 500); 
    }); 

    router.post('/', function(req, res, next) { 
    // socket can be accessed 
    }); 
    return router; 
}; 
module.exports = returnRouter; 

(Anmerkung: Ich habe eine Menge meiner eigenen Code aus, damit ich weiß nicht, ob diese Kopie und pasteable bereit ist, und Sie sollten wahrscheinlich überprüfen dieser Sockel ist nicht null)

Ohne setTimeout ist Sockel auf GET '/' nicht definiert. Zu meinem Verständnis muss die Seite zuerst rendern ... Seltsam, dass 200 manchmal nicht für mich funktioniert und 500 tut es. Ich kann es bei 500 lassen, aber das ist für ein Spiel, also ist die Zeit ziemlich wichtig.


Meine Fragen sind jetzt:

diese verbessert werden kann/ist es eine Möglichkeit, dies ohne SetTimeout tun kann? Sehe ich Clients mit diesem Code richtig an und bin ich (Frage # 4 da oben ^) effizient mit Socket.IO?

P.S. Wenn niemand diese Fragen beantwortet, werde ich dies bearbeiten, die Frage beantworten und meine Antwort als beste Antwort akzeptieren.

Antwort

2

Wenn Sie Sockets beim Routing in Node verwenden, ist es nicht so nützlich.

Wenn Sie zu einem anderen Namensraum navigieren (z. B. www.example.com -> www.example.com/somes-name-space), werden Ihre Front-End-Variablen gelöscht, und Sie müssen sie erneut senden. Dies funktioniert hervorragend, wenn Sie ein Objekt zusammen mit der GET-Anforderung für diesen Namensraum übergeben. Aber es braucht keine Steckdosen.

Es ist wie diese auf Ihrem Router Datei getan

var canAlsoBePassed = {some: "things"}; 
router.get('/', function(req, res, next) { 
    res.render('index', { items: "Can be passed directly", variables: canAlsoBePassed }); 
}); 

Für Steckdosen die beste Art von Anwendungen sind für einzelne Seite Apps oder AJAX Anfragen zu ersetzen. Eine weitere großartige Sache, die Sockets ermöglichen, ist, dass der Server Informationen pushen kann, ohne dass der Client danach fragt.

Um Ihre Frage zu SetTimeout zu beantworten, brauchen Sie dies nicht.

Stellen Sie sicher, dass das auf Ihrer Clientseite ausgeführte Socket-Skript darauf wartet, dass das Dokument geladen wird.

$(document).ready(function() { 

Wenn ein io.on (‚Verbindung‘ Ereignis ausgelöst wird auf Server-Seite Sie wissen, dass Sie einen neuen Client zu dienen.

emittieren ein Ereignis von der Server-Seite so etwas wie ein willkommenes Ereignis, das macht der Kunde einen bestimmten Raum beitreten. Sobald Sie sie in diesem Raum haben, können Sie für alle Veranstaltungen an diesem Raum emittiert werden hören.

Socket.io offiziellen Informationen

benutzerdefinierte Namespaces zum einrichten eines benutzerdefinierten Namespace Siehe, Sie können rufen die der Funktion auf der Server-Seite:

var nsp = io.of('/my-namespace'); 
nsp.on('connection', function(socket){ 
    console.log('someone connected'): 
}); 
nsp.emit('hi', 'everyone!'); 
On the client side, you tell Socket.IO client to connect to that namespace: 

var socket = io('/my-namespace'); 

nicht die genaueste Antwort auf Ihre Fragen sein könnte, aber ich hoffe, dass es Ihnen in die richtige Richtung schiebt.

Verwandte Themen