【问题标题】:Efficiency with JavaScript CallbacksJavaScript 回调的效率
【发布时间】:2012-04-26 18:37:09
【问题描述】:

我只是想确认我的怀疑。

我偶然发现了一篇文章,它建议以下列方式使用 Socket.io:

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

app.listen(8080);

// Some unrelated stuff

io.sockets.on('connection', function (socket) {
    socket.on('action1', function (data) {
        // logic for action1
    });

    socket.on('action2', function (data) {
        // logic for action2
    });

    socket.on('disconnect', function(){
        // logic for disconnect
    });
});

我觉得以下会更好地利用资源:

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

app.listen(8080);

// Some unrelated stuff

io.sockets.on('connection', function (socket) {
    socket.on('action1', action1);
    socket.on('action2', action2);
    socket.on('disconnect', disconnect);
});

function action1(data) {
    // logic for action1
}

function action2(data) {
    // logic for action2
}

function disconnect() {
    // logic for disconnect
}

我的感觉是,虽然处理connection事件的匿名函数只在内存中创建一次,但处理action1action2disconnect的匿名函数是在内存中为每个socket连接创建的.第二种方法的问题是socket 不再在范围内。

首先,我对创建函数的怀疑是真的吗?其次,如果是这样,有没有办法让socket 在命名函数的范围内?

【问题讨论】:

  • 我不熟悉 V8 内部结构,但它可能足够聪明,可以编译一次函数并每次都重新使用它,只是附加了不同的范围。
  • @ThiefMaster:根据 V8 邮件列表中的一位技术人员,是的,它“通常”是;见my answer to KPthunder's other question

标签: javascript node.js scope socket.io


【解决方案1】:

使用闭包有助于保持范围清洁:

io.sockets.on('connection', function () {
    function action1(data) {
        // logic for action1
    }
    function action2(data) {
        // logic for action2
    }
    function disconnect() {
        // logic for disconnect
    }
    return function (socket) {
        socket.on('action1', action1);
        socket.on('action2', action2);
        socket.on('disconnect', disconnect);
    }
}()); // <- note the immediate function call 

对于您的问题:

首先,我对创建函数的怀疑是真的吗?

是的。上面的闭包方法可以防止这种情况,回调函数只创建一次。加:都看到正确的父范围。

其次,如果是这样,有没有办法让socket 在命名函数的范围内?

socket 将在回调中以 this 的形式提供。

【讨论】:

  • 这个例子与使用匿名闭包没有区别——仍然为每个套接字连接创建了一个新的“action1”。不超过或少于原始代码示例。
  • @webnesto 这不是真的。是什么让你这么认为?
  • socket.on('foo', function(){});和函数 x(){}; socket.on('foo', x);在功能上是相同的。唯一的区别是,当闭包被命名时,可以再次引用它。
  • 在套接字连接外壳内定义“函数 action1”可确保为每个套接字连接定义函数 action1(实例化新方法)。与第一个示例中的匿名闭包没有什么不同。为什么认为这有什么不同?
  • OMG - 我是个白痴,没有仔细阅读。你是 100% 正确的。对此感到抱歉。
【解决方案2】:

你是对的,匿名方法是为每个连接创建的——如果你不需要范围,那么第二种方法确实可以避免这种情况。如果您需要套接字范围,则没有真正的方法可以避免它。如果您想将方法保留在外部(出于某些其他原因)并仍然保留范围,您可以随时:

//...
socket.on('action1', function(){
  action1.apply( socket, arguments );
} );
//... and so forth.

但这让你回到为每个连接创建一个方法签名,所以我不确定你会得到什么。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    • 2017-10-05
    相关资源
    最近更新 更多