Socket.io两次(或更多)发送消息

时间:2012-08-21 16:28:05

标签: javascript node.js push-notification socket.io push

我在node.js的server.js文件中有这段代码:

var app = require('http').createServer(handler), io = require('socket.io').listen(app);
var xml2js = require('xml2js'), parser = new xml2js.Parser(), fs = require('fs');

// creating the server ( localhost:8000 )
app.listen(8000);

/**
 * Esta función es la que envía el archivo js necesario para la comunicación
 * push con sockets
 * 
 * @param req
 * @param res
 */
function handler(req, res) {
    Request = require('url').parse(req.url, true);
    site = Request.query.site;
    entity = Request.query.entity;
    id = Request.query.id;

    fs.readFile(__dirname + '/client.js', 'utf8', function(err, data) {
        if (err) {
            console.log(err);
            res.writeHead(500);
            return res.end('Error loading client.js');
        }
        var dataString = data.toString();
        dataString = dataString.replace('confSite', site);
        dataString = dataString.replace('confEntity', entity);
        dataString = dataString.replace('confId', id);
        res.writeHead(200, {
            'Content-Type' : 'text/javascript;charset=UTF-8'
        });
        res.end(dataString);
    });
};

var listeners = {};
var parsers = {};
var listenersAndSockets = {};
var socketsOnListeners = {};
var watchers = {};
/**
 * Esta función es la que enviará la información que se actualice a los
 * clientes. Escuchará un archivo xml el cual envará al cliente una vez que este
 * haya cambiado
 */
io.sockets.on('connection', function(socket) {
    socket.on ('connect', function() {
        console.log('conectado');
    });
    socket.on('setup', function(config) {
        console.log('setup');
        var site = config.site;
        var entity = config.entity;
        var id = config.id;
        var listenerName = '' + site + entity + id + '';
        watchers[listenerName] = site + '/' + '/' + entity + '/' + id + '.xml';
        socketsOnListeners[socket.id] = listenerName;
        if (typeof socketsOnListeners[listenerName] == 'undefined') {
            socketsOnListeners[listenerName] = {};
        }
        socketsOnListeners[listenerName][socket.id] = socket.id;
        if (typeof listeners[listenerName] == 'undefined') {
            parsers[listenerName] = new xml2js.Parser();
            fs.stat(watchers[listenerName], function(err, stats) {
                if (err) {
                    fs.writeFile(watchers[listenerName], '');
                }
            });
            listeners[listenerName] = function(curr, prev) {
                fs.readFile(watchers[listenerName], function(err, data) {
                    parsers[listenerName].parseString(data);
                });
            };
            fs.watch(watchers[listenerName], listeners[listenerName]);
        }
        parsers[listenerName].addListener('end', function(result,a) {
            socket.volatile.emit('notification', result);
        });
    });

    socket.on('disconnect', function() {
        delete socketsOnListeners[socketsOnListeners[socket.id]][socket.id];
        if (socketsOnListeners[socketsOnListeners[socket.id]].lenght == 0) {
            fs.unwatch(watchers[socketsOnListeners[socket.id]]);
            delete watchers[socketsOnListeners[socket.id]];
        }
        delete socketsOnListeners[socket.id];
    });
});

在我的test.html中,我有这个:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Prueba de Push</title>
</head>
<body>

    <div id="div1">Este es un texto de prueba</div>

    <script src="http://10.0.0.113:8000/socket.io/socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
    <script src="http://10.0.0.113:8000/?site=levelup&entity=noticia&id=1"></script>

    <script>
        function test(data) {
            console.log(data);
            jQuery('#' + data.id).html(data.content);
        }
    </script>


</body>
</html>

Client.js是这样的:

var socket = io.connect('http://10.0.0.113:8000');
var config = {
    site : 'confSite',
    entity : 'confEntity',
    id : 'confId'
};

socket.emit("setup", config);
socket.on('reconnect', function() {
    socket.emit("setup", config);
});
// on every message recived we print the new datas inside the #container div
socket.on('notification', function(data) {
    _efbn(data.callback, window, data.response, data);
});

/**
 * Función que ejecuta una función por nombre. Puede usar namespaces
 * (algo.algo.algo.funct)
 * 
 * @see http://stackoverflow.com/questions/359788/javascript-function-name-as-a-string/359910#359910
 */
function _efbn(functionName, context) {
    var args = Array.prototype.slice.call(arguments);
    args = [ args[2], args[3] ]; // Fix para IE.
    var namespaces = functionName.split(".");
    var func = namespaces.pop();
    for ( var i = 0; i < namespaces.length; i++) {
        context = context[namespaces[i]];
    }
    try {
        if (typeof context[func] == 'function') {
            return context[func].apply(this, args);
        }
    } catch (e) {
        console.log(e);
    }
    return null;
}

在firefox中,当我修改服务器上的文件时,我收到两次或更多通知。有什么方法可以防止这种情况吗?我在node.js上读过一些关于群组的内容......这会对我有帮助吗?

1 个答案:

答案 0 :(得分:2)

您开始在setup事件中观看文件。在客户端setup可能会多次发生事件(reconnect事件)。对于每个watch调用,新的侦听器将添加到文件中。在设置之前,您需要检查文件中是否存在watch侦听器(对于此套接字)。在关闭套接字后,您还需要unwatch文件。否则你会得到内存泄漏。

<强>更新

您还需要移动

parser.addListener('end', function(result) {
    socket.volatile.emit('notification', result);
});

setup事件之外。