2014-01-29 77 views
1

我有一個socket.io服務器,它在每個socket.io連接中都有一個自定義方法'looper.output'。每當我關閉一個socket.io連接時,我會啓動另一個自定義方法'looper.disconnect',它應該爲關閉的客戶端刪除'output'偵聽器。我的問題是,無論何時關閉客戶端,looper.disconnect不僅會從該客戶端中刪除偵聽器,還會從關閉客戶端後啓動的每個客戶端中刪除偵聽器。例如,如果我有4個客戶端A,B,C和D,它們也按該順序連接到服務器,並且客戶端C關閉; looper.disconnect將刪除C和D的偵聽器,但只保留A和B.RemoveListener刪除'this'listener後啓動的所有監聽器

我需要更改哪些內容才能使looper.disconnect僅刪除調用它的客戶端的偵聽器?在上面的例子中,我只想要刪除客戶端C的偵聽器。

var express = require('express'); 
var http = require('http'); 
var spawn = require('child_process').spawn; 
var util = require('util'); 
var fs = require('fs'); 
var EventEmitter = require('events').EventEmitter; 
var sys = require('sys'); 

var app  = express(), 
    server = http.createServer(app), 
    io  = require('socket.io').listen(server); 

function Looper(req) { 
    this.req = req; 
    EventEmitter.call(this); 
} 
sys.inherits(Looper, EventEmitter); 

Looper.prototype.run = function() { 
    var self = this; 
    var cmd = spawn('./flow',[this.req]); // <-- script that outputs req every second 
    cmd.stdout.setEncoding('utf8'); 
    cmd.stdout.on('data', function(data) { 
     self.emit('output',data); 
    }); 
} 

Looper.prototype.output = function(callback) { 
    this.output.outCallback = function(mydata) { 
     return callback(mydata.trim()); 
    } 
    this.on('output', this.output.outCallback); 
} 

Looper.prototype.disconnect = function() { 
    this.removeListener('output',this.output.outCallback); 
} 

var looper = new Looper('blah'); 
looper.run(); 

app.use(express.static(__dirname + '/public')); 

app.get('/', function(req, res) { 
    res.send(
     "<script src='/socket.io/socket.io.js'></script>\n"+ 
     "<script>\n"+ 
     "\tvar socket=io.connect('http://127.0.0.1:3000');\n"+ 
     "\tsocket.on('stream', function(data) {\n"+ 
     "\t\tconsole.log(data);\n"+ 
     "\t});\n"+ 
     "</script>\n" 
    ); 
}); 
server.listen(3000); 

io.sockets.on('connection', function(webSocket) { 
    looper.output(function(res) { 
     webSocket.emit('stream',res+":"+webSocket.id); 
    }); 

    webSocket.on('disconnect', function() { 
     looper.disconnect(); 
    }); 
}); 

回答

1

您可以將聽者總是和聽者功能將數據發送到添加到彎對象的所有回調。

由session_id爲每個客戶端確定回調。

var express = require('express'); 
var http = require('http'); 
var spawn = require('child_process').spawn; 
var util = require('util'); 
var fs = require('fs'); 
var EventEmitter = require('events').EventEmitter; 
var sys = require('sys'); 

var app  = express(), 
    server = http.createServer(app), 
    io  = require('socket.io').listen(server); 

function Looper(req) { 
    this.req = req; 
    Looper.prototype.outCallbacks = {}; 
    EventEmitter.call(this); 
} 
sys.inherits(Looper, EventEmitter); 

Looper.prototype.callAllCallbacks = function(data) { 
    for (var callback in this.outCallbacks) { 
    if (this.outCallbacks.hasOwnProperty(callback)) { 
     this.outCallbacks[callback](data); 
    } 
    } 
} 

Looper.prototype.run = function() { 
    var self = this; 
    var cmd = spawn('./flow',[this.req]); // <-- script that outputs req every second 
    cmd.stdout.setEncoding('utf8'); 
    cmd.stdout.on('data', function(data) { 
    self.emit('output',data); 
    }); 

    this.on('output', this.callAllCallbacks); 
} 

Looper.prototype.addCallback = function(session_id, callback) { 
    this.outCallbacks[session_id] = function(mydata) { 
    return callback(mydata.trim()); 
    } 
} 

Looper.prototype.disconnect = function(session_id) { 
    delete this.outCallbacks[session_id]; 
} 

var looper = new Looper('blah'); 
looper.run(); 

app.use(express.static(__dirname + '/public')); 

app.get('/', function(req, res) { 
    res.send(
     "<script src='/socket.io/socket.io.js'></script>\n"+ 
     "<script>\n"+ 
     "\tvar socket=io.connect('http://127.0.0.1:3000');\n"+ 
     "\tsocket.on('stream', function(data) {\n"+ 
     "\t\tconsole.log(data);\n"+ 
     "\t});\n"+ 
     "</script>\n" 
    ); 
}); 
server.listen(3000); 

io.sockets.on('connection', function(webSocket) { 
    var session_id = webSocket.id; 

    looper.addCallback(session_id, function(res) { 
    webSocket.emit('stream',res+":"+webSocket.id); 
    }); 

    webSocket.on('disconnect', function() { 
    looper.disconnect(session_id); 
    }); 
}); 
+0

感謝您的建議,我通過你的代碼去和更新,它得到它的工作。這將工作,但有可能完成我原來想要做的事情嗎?這似乎更像是解決問題的辦法,而不是答案。 –

1

我真的不明白爲什麼它會以這種方式失敗,但您的主要問題是您將所有功能的引用保存在同一個地方。

另一種選擇是有這樣每個客戶端的回調函數參考:

var express = require('express'); 
var http = require('http'); 
var spawn = require('child_process').spawn; 
var util = require('util'); 
var fs = require('fs'); 
var EventEmitter = require('events').EventEmitter; 
var sys = require('sys'); 

var app  = express(), 
    server = http.createServer(app), 
    io  = require('socket.io').listen(server); 

function Looper(req) { 
    this.req = req; 
    EventEmitter.call(this); 
} 
sys.inherits(Looper, EventEmitter); 

Looper.prototype.run = function() { 
    var self = this; 
    var cmd = spawn('./flow',[this.req]); // <-- script that outputs req every second 
    cmd.stdout.setEncoding('utf8'); 
    cmd.stdout.on('data', function(data) { 
     self.emit('output',data); 
    }); 
} 

Looper.prototype.output = function(callback) { 
    this.on('output', callback); 
} 

Looper.prototype.disconnect = function(callback) { 
    this.removeListener('output', callback); 
} 

var looper = new Looper('blah'); 
looper.run(); 

app.use(express.static(__dirname + '/public')); 

app.get('/', function(req, res) { 
    res.send(
     "<script src='/socket.io/socket.io.js'></script>\n"+ 
     "<script>\n"+ 
     "\tvar socket=io.connect('http://127.0.0.1:3000');\n"+ 
     "\tsocket.on('stream', function(data) {\n"+ 
     "\t\tconsole.log(data);\n"+ 
     "\t});\n"+ 
     "</script>\n" 
    ); 
}); 
server.listen(3000); 

io.sockets.on('connection', function(webSocket) { 
    var callback = function(res) { 
     webSocket.emit('stream',res.trim()+":"+webSocket.id); 
    } 

    looper.output(callback); 

    webSocket.on('disconnect', function() { 
     looper.disconnect(callback); 
    }); 
}); 
+0

另一個可靠的答案。這個更符合原始問題的運作方式。我仍然想知道爲什麼原始代碼無法正常工作。感謝所有的幫助。 –