RemoveListener删除在'this'侦听器之后启动的所有侦听器

时间:2014-01-29 17:23:19

标签: javascript node.js socket.io listener

我有一个socket.io服务器,它有一个自定义方法' looper.output'在每个socket.io连接里面。每当我关闭socket.io连接时,我都会启动另一种自定义方法' looper.disconnect'应该删除'输出'关闭的客户端的监听器。我的问题是,每当客户端关闭时,looper.disconnect不仅会从该客户端删除侦听器,而且还会从关闭的客户端之后启动的每个客户端中删除侦听器。

例如,如果我有4个客户端A,B,C和D,它们也按顺序连接到服务器并且客户端C关闭; looper.disconnect将删除C和D的侦听器,但只留下A和B.

我需要更改什么才能使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();
    });
});

2 个答案:

答案 0 :(得分:1)

您可以始终打开侦听器并在侦听器函数中将数据发送到添加到looper对象的所有回调。

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);
    });
});

答案 1 :(得分: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);
    });
});