分类: Node.js

Organizing and Reusing Node functionality






(文章节选之 – Node in Action ©Manning Publications Co)
In some language implementations, such as PHP and Ruby, incorporating the logic from another file (we’ll call this the “included” file) can mean all the logic executed in the included file affects the global scope. This means that any variables created and functions declared in the included file risk overwriting those created and declared by the application.
and in order avoid by same method name in different library, PHP using namespaces, and ruby offers similar functionality through “modules”

(在大多数的计算机语言的运用中,例如PHP和Ruby,我们习惯于将各种逻辑程序,安装功能分装在不同的文件中,然后利用“lncluded”语句将他们带入同一个“运行空间(excution envirement)”.但是,不同的程序,有时候会出现重名字的funcion 或者 variables,这里,例如PHP,运用了”namespace”来解决,Ruby也有module,来解决这个问题。)

Node modules bundle up code for reuse, but don’t alter global scope. They, in fact, allow you to select what functions and variables from the included file are exposed to the application. If returning more than one function/variable then a module can specify these by setting the properties of an object called “exports”.

(Node在解决这个问题的时候,别出新意,它提供了“exports”功能,让你自由的选择,那些”function”和”variables”,你可以共享给其他库程序
简单的一个理解,如果你写过java或者C#:
– require(code) = include
– export (node) = public )

here we using a simple example to show you how node do it.
To show how a basic module is created, let’s add some currency conversion functionality to a file named “currency.js”. This file will contain two functions that will convert Canadian dollars to US dollars, and vice versa:
(这里举出一个例子来说明,Node如何实现一个简单的module,这里我们写出一个汇率装换的module,文件名字”currency.js”,我们将提供美元和加元之间的转化功能。)

var canadianDollar = 0.91;
function roundTwoDecimals(amount) {
      return Math.round(amount * 100) / 100;
  }
exports.canadianToUS = function(canadian) {
      return roundTwoDecimals(canadian * canadianDollar);
  }
exports.USToCanadian = function(us) {
      return roundTwoDecimals(us / canadianDollar);
  }

Note that only two properties of the exports object are set. This means only the two functions, canadianToUS and USToCanadian can be accessed by the application including the module. The variable canadianDollar acts as a private variable that effects the logic in canadianToUS and USToCanadian but can’t be directly accessed by the application.
(这里只有“canadianToUS”和“USToCanadian”两个function可以被起来库文件引用[public],canadianDollar相当与一个private variable)
To utilize your new module, you can use Node’s require function, which takes as an argument a path to the module you wish to use.
(这里来看看,如何使用我们新的Module)

var currency = require('./currency');
//带入
//The path begins with './' to indicate that the module exists 
//within the same directory as the application script
console.log('50 Canadian dollars equals this amount of US dollars:');
console.log(currency.canadianToUS(50));

console.log('30 US dollars equals this amount of Canadian dollars:');
console.log(currency.USToCanadian(30));

Populating the exports object of a module gives you a simple way to group reusable code in separate files.

module.exports

(下面的例子,简单说明了module.export和export的区别,export只可以”export function”,如果如下面的例子,你需要export一个object[注意javascript下没有class这个说法],你需要用module.export)

The currency convertor module created earlier in this section, for example, could be redone to return a JavaScript class, rather than an object containing functions. An object-oriented implementation could behave something like the following.

var Currency = require('./currency')
  , canadianDollar = 0.91;
currency = new Currency(canadianDollar);
console.log(currency.canadianToUS(50));

To create a module that will return anything other than an object you might guess that you simply need to set exports to whatever you want to return. This, however, won’t work as Node expects exports to remain an object. The following module code attempts to set exports to a class and, when you try to use it with the previous code, a TypeError: object is not a function exception will be raised.

var Currency = function(canadianDollar) {
  this.canadianDollar = canadianDollar;
}
Currency.prototype.roundTwoDecimals = function(amount) {
  return Math.round(amount * 100) / 100;
}
Currency.prototype.canadianToUS = function(canadian) {
  return this.roundTwoDecimals(canadian * this.canadianDollar);
}
Currency.prototype.USToCanadian = function(us) {
  return this.roundTwoDecimals(us / this.canadianDollar);
}
//exports = Currency;//won't works
module.exports = Currency //works

In order to get the previous module code to work as expected, you’d need to replace exports with module.exports. The module.exports mechanism is provided as a way to work around Node’s inabiliy to set exports to something other than an object. If you create a module that populates both exports and module.exports, module.exports will be returned and exports will be ignored.

Reusing modules using the “node_modules” folder

Requiring modules that exist relative, in the filesystem, to an application is useful for organizing application-specific code,For code reuse Node includes a unique mechanism that allows modules to be required without knowing their location in the filesystem. This mechanism is the use of “node_modules” directories.
If the module identifier passed to 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_modules, 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.
(如果你要一直用require()来调入你的库文件而不想指明文件地址,你可以建立一个叫“node_modules”的文件夹,然后把库文件放在里面,node会自动找寻)

if a module is a directory, the file in the module directory that will be evaluated must be named “index.js”, unless specified otherwise by a file in the module directory named “package.json”. To specify an alternative to “index.js”, the “package.json” file must contain JavaScript Object Notation (JSON) data defining an object with a key named “main” that specifies the path, within the module directory, to the main file.
(如果你的module是一个文件夹,你需要遵循几个规则。
1.必须有index.js文件
2.如果没有index.js 文件的话,那必须有package.json 文件,并且用”main”: “xxx.js”来指出module的最初执行文件(相当与index.js)




发表评论