Node.js 一个 Socket.IO 程序的疑问

daqing · 2015年08月13日 · 最后由 daqing 回复于 2015年08月14日 · 7881 次阅读

最近写了一个简单的 Socket.IO 程序,代码如下:

var io = require('socket.io')(8801);
var redis = require('reds');

io.on('connection', function(socket) {
    var client = redis.createClient();
    client.on('message', function(channel, data) {
        var message = JSON.parse(data);
        io.emit(message['type'], message);
    });

    client.subscribe('node');
});

这段代码工作正常,但我的疑惑是:在connection回调函数执行完以后,client变量不就被垃圾回收了吗?然后到 redis 的连接应该会断开了啊,为什么实际上没有断开呢?

@daqing connection 回调函数中你用到了 redis 这个方法外的环境变量. 其实这个回调函数已经是形成一个闭包, 回调方法中的所有成员变量都会一直存在了 (也用到了 io). 回调方法的已经将当前的 Execution Context 和回调方法外的 Execution Context 这两个 Context 放到他的 scope chain 中去了.

Execution Context, Scope Chain

Javascript 不是很熟悉,但是这个应该是共通的。传入的 function 其实就是一个 closure,是带有当前 scope 的 binding 的,比如这里的io, redis, connection 触发时,调用传入的 function,创建一个 client,所以其实每次调用的时候都是一个新的 client。

@yanguango 其实如果传入的 function 里面没有调用方法外的环境变量的话还是不存在闭包的, 只是 function first class 传入一个 function 作为 param 罢了.

不过, 这个每次 connection 回调函数被触发, 应该每次都被创建了一个新的 client 实例, 并且都因闭包形成一直存在于内存中

client 应该是不会被 GC 的,毕竟在用。

connection 事件中创建的 client 会去注册一些回调函数,为了保持状态,注册回调函数的时候会把 this 绑定进去,类似于

sock.on("data", client.ondata.bind(client));

这样这个回调函数就会有 client 的引用,所有 client 不会被回收。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号