Showing posts with label nodejs. Show all posts
Showing posts with label nodejs. Show all posts

Monday, August 26, 2013

Node.js fs.watchFile error EventEmitter memory leak detected . Max listeners

This happens when fs.WatchFile is called on the same file multiple times.
Explaination
fs module contains a local object "statWatchers" {} to track files being watched.
So when fs.watchFile('fileX') is called a new statWatcher object is created if one does not exits and stored it in the "statWatchers" object against the file name. If there is already a statWatcher object associated with this file, it is returned.
statWatcher["fileX"] = new statWatcher();
And then calls addListener('change', listener) on the statWatcher object associated with this file.
Incase fs.watchFile is called for 11 times on "fileX", it will result in calling addListener on the statWatcher for event "change" 11 times.
EventEmitter throws an error if tried to add more than 11 listeners for the same event.

require in nodejs

Assuming this is the first time the module is being required.

For example ,

var x = require('file1.js');
contents of file1.js;
====================
module.exports = '123'

When the above statement is executed, a 'Module' object is created.
Module constructor function is provided below,

function Module(id, parent) {
    this.id = id;
    this.exports = {}; // the exports property which is actually return on require
    this.parent = parent;
    if (parent && parent.children) {
        parent.children.push(this);
    }

    this.filename = null;
    this.loaded = false;
    this.children = [];
}

As you see each module object has a property with name 'exports'.
This is what is eventually returned as part of require.

Next step of require is to wrap the contents of file1.js into an anonymous function like below :

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

And the above anonymous function is invoked the following way, module here refers to the Module Object created earlier.

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");

As we can see inside the function , exports formal argument refers to module.exports.
In essence its a convenience provided to the module programmer.

However this convenience need to be exercised with care.
In any case if trying to assign a new object to exports ensure we do it this way.

exports = module.exports = {};

If we do it following way wrong way, module.exports will still be pointing to the object created as part of module instance.

exports = {};

As as result adding anything to the above exports object will have no effect to module.exports object and nothing will be exported or returned as part of require.

Friday, May 4, 2012

nodejs : Anatomy of http.request

http.request() method will create createRequest Object.This will inturn call Agent's addRequestMethod.
This will see if there is any already created socket for host:port combination.If the no of sockets created for this combination is < than the set configuration max limit value, a socket is created using net.createconnection.After the socket is returned createRequestObject's onSocket method is called which will create a function and add it to the event queue to be executed as part of next tick.This created function will set up socket's ondata.

sockets's ondata function creates a parser and this parser parses the data and takes necessary actions.This parser creates a IncomingMessage object and populates the response.on complete it will emit response event on createRequest Object. This will call the callback we passed while initiating the request(http.request)

clientResponse is a http.IncomingMessage object, an eventEmitter that gets built and populated by the parser whose execute method is called when socket data is available,
   
    the callback we are passing gets called after the headers are processed, at which time we will add listeners for the events 'data' & 'end'.
       
    Parser while parsing the message body will emit 'data' event on clientResponse.
    Parser will emit 'end' event on messageComplete