2012-04-14 5 views
2

Я просто хотел подтвердить свое подозрение.Эффективность с обратными вызовами JavaScript

я наткнулся на статью, которая рекомендовала использовать 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, создается только один раз в памяти, анонимные функции, которые обрабатывают action1, action2 и disconnect, созданы в память y для каждого соединения сокета. Проблема со вторым подходом заключается в том, что socket больше не входит в сферу действия.

Итак, во-первых, мое подозрение о создании функций истинно? И во-вторых, если это так, то можно получить socket в области названных функций?

+1

Я не знаком с внутренними компонентами V8, но он может быть достаточно умным для компиляции функции один раз и повторного использования ее каждый раз, только с другой областью применения. – ThiefMaster

+1

@ThiefMaster: По словам одного из техников в списке рассылки V8, да, это «нормально»; см. [мой ответ на другой вопрос KPthunder] (http://stackoverflow.com/a/10160351/157247). –

ответ

5

Использование закрытия помогает сохранить объем чистой:

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 в обратных вызовах.

+0

В этом примере нет никакой разницы, кроме использования анонимных закрытий. По-прежнему существует новое «действие1», созданное для каждого подключения сокета. Не больше или меньше, чем в исходном образце кода. – webnesto

+0

@webnesto Это неправда. Что заставляет вас думать, что? – Tomalak

+0

socket.on ('foo', function() {}); и функция x() {}; socket.on ('foo', x); функционально одинаковы. Единственное различие заключается в том, что при названии закрытия есть возможность для другой ссылки на него. – webnesto

1

Вы правы, что для каждого соединения создаются анонимные методы, и если вам не нужна область видимости, то второй способ этого избежать. Если вам нужна область сокета, нет реального способа избежать этого. Если вы хотите сохранить методы внешними (по какой-то другой причине) и по-прежнему держать сферу, вы могли бы всегда:

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

Но есть вас к созданию метода подписи для каждого соединения, поэтому я не уверен, что бы вы набрали.

Смежные вопросы