[~/javascript/node.js/creating_modules(master)]$ cat foo.js var circle = require('./circle.js'); console.log( 'The area of a circle of radius 4 is ' + circle.area(4));
[~/javascript/node.js/creating_modules(master)]$ cat circle.js var PI = Math.PI; exports.area = function (r) { return PI * r * r; }; exports.circumference = function (r) { return 2 * PI * r; };
[~/javascript/node.js/creating_modules(master)]$ node foo.js The area of a circle of radius 4 is 50.26548245743669
El módulo circle.js
exporta las funciones area()
y circumference()
. Para exportar un objeto lo añadimos
al objeto expecial exports
.
Las variables locales al módulo serán privadas.
En este ejemplo la variable PI
es privada a circle.js
.
[~/javascript/node.js/creating_modules(master)]$ node debug foo.js < debugger listening on port 5858 connecting... ok break in foo.js:1 1 var circle = require('./circle.js'); 2 console.log( 'The area of a circle of radius 4 is ' 3 + circle.area(4)); debug> n break in foo.js:2 1 var circle = require('./circle.js'); 2 console.log( 'The area of a circle of radius 4 is ' 3 + circle.area(4)); 4 debug> repl Press Ctrl + C to leave debug repl > circle { circumference: [Function], area: [Function] } > circle.area(2) 12.566370614359172 > PI ReferenceError: PI is not defined >
[~/javascript/node.js/creating_modules/cycles(master)]$ cat a.js console.log('a starting'); exports.done = false; var b = require('./b.js'); console.log('in a, b.done = %j', b.done); exports.done = true; console.log('a done');
[~/javascript/node.js/creating_modules/cycles(master)]$ cat b.js console.log('b starting'); exports.done = false; var a = require('./a.js'); console.log('in b, a.done = %j', a.done); exports.done = true; console.log('b done');
[~/javascript/node.js/creating_modules/cycles(master)]$ cat main.js console.log('main starting'); var a = require('./a.js'); var b = require('./b.js'); console.log('in main, a.done=%j, b.done=%j', a.done, b.done);When
main.js
loads a.js
, then a.js
in turn loads
b.js
. At that point, b.js
tries to load a.js
. In
order to prevent an infinite loop an unfinished copy of the a.js
exports object is returned to the b.js
module. b.js
then
finishes loading, and its exports object is provided to the a.js
module.
By the time main.js
has loaded both modules, they're both finished. The
output of this program would thus be:
[~/javascript/node.js/creating_modules/cycles(master)]$ node main.js main starting a starting b starting in b, a.done = false b done in a, b.done = true a done in main, a.done=true, b.done=true
.js
,
.json
, and then .node
.
.js
files are interpreted as JavaScript text files, and .json
files are parsed as JSON text files. .node
files are interpreted as compiled addon modules
'/'
is an absolute path to the file. For example,
require('/home/marco/foo.js')
will load the file at /home/marco/foo.js
.
'./'
is relative to the file calling require().
'./'
to indicate a file, the module is either a
core module or is loaded from a node_modules
folder.
require()
will throw an Error with its code property set to MODULE_NOT_FOUND
.
require()
is not a native module,
and does not begin with '/'
, '../'
, or './'
, then node starts at the
parent directory of the current module, and adds /node_mo1dules
, and
attempts to load the module from that location.
For example, if the file at '/home/ry/projects/foo.js'
called
require('bar.js'
), then node would look in the following locations,
in this order:
/home/ry/projects/node_modules/bar.js /home/ry/node_modules/bar.js /home/node_modules/bar.js /node_modules/bar.js
This allows programs to localize their dependencies, so that they do not clash.
There
are a few ways in which a folder may be passed to require()
as an
argument.
package.json
file in the root of the
folder, which specifies a main
module.
An example package.json
file
might look like this:
{ "name" : "some-library", "main" : "./lib/some-library.js" }
If this was in a folder at
./some-library
, then require('./some-library')
would attempt
to load ./some-library/lib/some-library.js
.
This is the extent of Node's awareness of package.json
files.
package.json
file present in the directory, then node will
attempt to load an
index.js
or
index.node
file out of that directory.
For
example, if there was no
package.json
file in the above example, then
require('./some-library')
would attempt to load:
./some-library/index.js ./some-library/index.node
require('foo')
will get exactly
the same object returned, if it would resolve to the same file.
require('foo')
may not cause the module code
to be executed multiple times. This is an important feature. With it,
partially done objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
node_modules folders
), it is not a guarantee that
require('foo')
will always return the exact same object, if it would
resolve to different files.
module
free variable is a reference to the object
representing the current module.
module.exports
is the
same as the exports object.
module
isn't actually a global but rather
local to each module.
Module
system.
Sometimes this is not acceptable,
many want their module to be an instance of some class.
To do this assign the desired export object to module.exports
.
[~/javascript/node.js/creating_modules/module_exports(master)]$ cat a.js var EventEmitter = require('events').EventEmitter; module.exports = new EventEmitter(); // Do some work, and after some time emit // the 'ready' event from the module itself. setTimeout(function() { module.exports.emit('ready'); }, 1000);
$ cat main.js var a = require('./a'); a.on('ready', function() { console.log('module a is ready'); });
$ node main.js module a is ready
module.exports
debe hacerse inmediatamente.
No puede hacerse en un callback.
LOAD_AS_FILE(Y + X)
LOAD_AS_DIRECTORY(Y + X)
LOAD_NODE_MODULES(X, dirname(Y))
LOAD_AS_FILE(M)
DIRS=NODE_MODULES_PATHS(START)
LOAD_AS_FILE(DIR/X)
b. LOAD_AS_DIRECTORY(DIR/X)
Casiano Rodríguez León