Fundamentals: Callbacks in Node?

159 views
Skip to first unread message

David J Lima

unread,
Aug 10, 2014, 10:13:37 AM8/10/14
to nod...@googlegroups.com

In the plain javaScript world I've learned that nested functions can be problematic because the inner function is "re-created" every time the outer function is called. Apparently the inner function is garbage collected and the constant re-creation of it has a cost on performance.

function outer(a) {
    function inner(arg1,arg2){
        return arg1 + arg2;
    }
    return inner(a, 6);
}
myVar = outer(4);

Are asynchronous callback functions typical in Node "re-created" every time they are fired? Take the following common Node construct:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

Is the above callback "re-created" every time a client GETs or POSTs the server? If so, would it be better to always de-couple the callbacks as :

function handleGET(req, res) {
   res.writeHead(200, {'Content-Type': 'text/plain'});
   res.end('Hello World\n');
}

http.createServer(handleGET).listen(1337, '127.0.0.1');

as a related bonus question, are event functions re-created too? Would they benefit from prior declaration?

myObj.on('someEvent', function someFunction() {...});

vs.

function someFunction() {...}
myObj.on('someEvent', someFunction);

Matt

unread,
Aug 11, 2014, 2:00:54 PM8/11/14
to nod...@googlegroups.com
I don't know where you heard that, but it's not true of V8 (or I doubt of any modern JS engine). There are plenty of benchmarks out there that can prove this.

You can however separate out for basic code hygiene - you get a lot of indentation with nested callbacks.

Matt.


--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/nodejs/3101820e-7425-42b2-b001-3a173c2fbd68%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Fedor Indutny

unread,
Aug 11, 2014, 2:01:43 PM8/11/14
to nod...@googlegroups.com
It is created only once.

However, if you define function in a closure - it'll be allocated each time the closure is executed.


--

Fedor Indutny

unread,
Aug 11, 2014, 2:15:50 PM8/11/14
to nod...@googlegroups.com
Matt,

This couldn't happen with any other js-engine, because of the ECMAScript semantics. The code that creates request handler closure is executed only once, which means that the closure is created only once.

Cheers,
Fedor.


greelgorke

unread,
Aug 12, 2014, 3:08:41 AM8/12/14
to nod...@googlegroups.com
The first example with outer and inner functions and the other two are different. in the first example you create an inner function in the body of the outer, so the creation code gets executed every time the outer function is.

in the other two examples the callback creation code is part of the argument list and executed once (as far as you don't create servers in series of course)

Angel Java Lopez

unread,
Aug 12, 2014, 3:23:23 PM8/12/14
to nod...@googlegroups.com
Interesting topic

About

"in the other two examples the callback creation code is part of the argument list and executed once (as far as you don't create servers in series of course)"

I expected

in the other two examples the callback creation code is part of the argument list and COMPILED once, bind ONCE to any present closure, give it to the server logic, and it is invoked in EACH request 


About
"The first example with outer and inner functions and the other two are different. in the first example you create an inner function in the body of the outer, so the creation code gets executed every time the outer function is."

I expected

In the first example you create an inner function in the body of the outer, BUT IT is compiled ONCE, as the outer one. Then, at invocation of the outer, the ALREADY compiled inner function is bind to any present closure (I guess that a clever compiler could identify that the inner function has no reference to free variables, only to locals and arguments, so no "external" closure is needed)

The first example was

function outer(a) {
    function inner(arg1,arg2){
        return arg1 + arg2;
    }
    return inner(a, 6);
}
myVar = outer(4);
The server example was

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
Is this the case?

Angel "Java" Lopez
@ajlopez

--
Job board: http://jobs.nodejs.org/
New group rules: https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
---
You received this message because you are subscribed to the Google Groups "nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nodejs+un...@googlegroups.com.
To post to this group, send email to nod...@googlegroups.com.

greelgorke

unread,
Aug 13, 2014, 2:50:38 AM8/13/14
to nod...@googlegroups.com

Inline :)


Interesting topic

About

"in the other two examples the callback creation code is part of the argument list and executed once (as far as you don't create servers in series of course)"

I expected

in the other two examples the callback creation code is part of the argument list and COMPILED once, bind ONCE to any present closure, give it to the server logic, and it is invoked in EACH request 
 
let me rephrase: The creation code is the function expression. this expression is executed not the function itself. you are right: the code is compiled, executed (execution of this code creates a function object) and bound once. the single function object is passed to the server creation code and will be invoked on every request. just a small misinterpretation of my statement :)



About
"The first example with outer and inner functions and the other two are different. in the first example you create an inner function in the body of the outer, so the creation code gets executed every time the outer function is."

I expected

In the first example you create an inner function in the body of the outer, BUT IT is compiled ONCE, as the outer one. Then, at invocation of the outer, the ALREADY compiled inner function is bind to any present closure (I guess that a clever compiler could identify that the inner function has no reference to free variables, only to locals and arguments, so no "external" closure is needed)

yes. for the first run of the complete code the inner function statement is compiled once, BUT on each invocation of outer a new function object of inner is created and bound and, as the outer code says, invoked.
 

The first example was

function outer(a) {
    function inner(arg1,arg2){
        return arg1 + arg2;
    }
    return inner(a, 6);
}
myVar = outer(4);
The server example was

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
Is this the case?

the first case will create a function object on each call of outer. just checked in node:

> function outer(){return function inner(){ }}
undefined
> var inner1 = outer()
undefined
> var inner2 = outer()
undefined
> inner1 === inner2
false


in the second the request handler function object is created once and is reused on each request call.

A note on compile: on the fist run the whole code is compiled once, but function bodies are not necessarily executed at this point, so not all function objects are created directly, but their blueprints are. However, the optimizing compiler might recompile some of them, so it doesn't make much sense to create the function object ahead of time, since they can be inlined. I could be wrong here, but this is what i think.

Reply all
Reply to author
Forward
0 new messages