构建node.js中需要的库的最佳实践
我有几个包含帮助函数的实用程序库,我想加载它们,以便从控制器使用它们,我想知道 在node中编码实用程序库的最佳实践是什么 我有点困惑,因为有几种方法可以做到这一点,我不确定什么是最好的/更合适的/更可靠的。这里有两个选项,但我想知道它们是否是最好的(例如,我见过使用构建node.js中需要的库的最佳实践,node.js,design-patterns,require,Node.js,Design Patterns,Require,我有几个包含帮助函数的实用程序库,我想加载它们,以便从控制器使用它们,我想知道 在node中编码实用程序库的最佳实践是什么 我有点困惑,因为有几种方法可以做到这一点,我不确定什么是最好的/更合适的/更可靠的。这里有两个选项,但我想知道它们是否是最好的(例如,我见过使用module.exports=exports=function(){},等等的代码段) //选项1.js //选项2.js "use strict"; module.exports = { test1 : func
module.exports=exports=function(){}
,等等的代码段)
//选项1.js
//选项2.js
"use strict";
module.exports = {
test1 : function(){ console.log('soy test1')},
test2 : function(){ console.log('soy test2')}
};
//test_controller.js
/* Requiring helpers in different ways */
var option1 = require('./option1.js')();
var option2 = require('./option2.js');
对于无状态实用程序库,option2.js是一种选择,因为不需要
模块中的代码。每次require
时都会导出要执行的
,这就是调用require('./option1.js')()
使用option1.js时发生的情况
另一方面,如果您的模块公开了创建保持状态的对象的构造函数,那么您需要option1.js。比如说,
person.js:
module.exports = function(firstName,lastName){
this.firstName = firstName;
this.lastName = lastName;
};
然后使用它:
var Person = require("./person");
var person1 = new Person("Foo","Bar");
var person2 = new Person("Joe","Shmoe");
option1.js(如上所示)的另一个优点是,它允许您将参数传递到模块中。我认为我的文件分为三个部分: 第1节:CommonJS依赖项 您不需要任何额外的包装函数。所有节点模块都由node.js在一个函数中创建,这样做没有任何好处,只会增加混乱 第2节:普通JavaScript代码 如果需要的话,这应该是带有少量支持变量或顶级模块代码的函数
var MY_CONST = 42;
function helper1() {
//excellent code here
}
function helper2() {
//excellent code here
}
保持第2节纯JS。不要在中间的“纯”部分使用commonJS习惯用法。不要使用模块
,导出
,要求
,等等。这只是我个人的指导原则,因为JS本身是稳定的,但打包到模块中仍然需要很多更改,最好将无关的、可能更改的公共JS位与感兴趣的代码位分开。ECMAScript 6模块最有可能在几年内取代CommonJS,因此,保持第2节为纯ECMAScript 5并制作一个“CommonJS三明治”,让您自己更容易做到这一点™" 我喜欢这样称呼它
第3节:公共出口
- 将所有导出放在末尾还可以让您快速了解公共API是什么,并防止由于不小心的复制/粘贴而意外导出属性
- 我更喜欢上面的
语法,而不是将exports.foo=foo;
分配给一个新的对象文字。我发现这避免了对象文字的最后一个属性的尾部逗号问题module.exports
- 用你的
或require
语句做任何其他事情几乎肯定是不必要的,也是不必要的花哨或魔术。在你获得进步之前,不要在这里做任何花哨的事情。(即使如此,如果你不是TJ Holowaychuk,你可能只是在做傻事)exports
var foo = require("foo");
function doubleFoo(value) {
return foo(value) * 2;
}
function tripleFoo(value) {
return foo(value) * 3;
}
exports.doubleFoo = doubleFoo;
exports.tripleFoo = tripleFoo;
构造函数
如果您的模块是面向对象的类设计,请导出构造函数
function GoCart() {
this.wheels = 4;
}
GoCart.prototype.drive = function drive() {
//vroom vroom
}
module.exports = GoCart;
工厂/配置关闭函数
一旦你掌握了以上两种模式(真的!),并且自信地导出一个包含选项的工厂函数,也许还可以做一些其他动态的事情,那么就去做吧,但如果有疑问,就坚持前两种更简单的选择
//do-stuff.js
function doStuff(howFast, what) {
return "I am doing " + what + " at speed " + howFast;
}
function setup(options) {
//The object returned by this will have closure access to options
//for its entire lifetime
return {doStuff: doStuff.bind(null, options.howFast)};
}
module.exports = setup;
所以你可以像这样使用它
var doStuff = require("./do-stuff")({howFast: "blazing speed"});
console.log(doStuff.doStuff("jogging"));
//"I am doing jogging at speed blazing speed"
谢谢@go oleg。关于用例和性能的非常有趣的评论:)非常好的回答@Peter。对模块设计非常有用。我会记住你的建议。请你提供关于“导出一个工厂函数,该函数包含选项,可能做一些其他动态的事情”的示例/链接“。我对在node.js代码中应用更多的架构技术感兴趣。这个答案已经过时了,因为它没有解决高级的新导出/导入语法。这仍然是很好的信息,但它是不完整的,而且新语法有性能优势(也可以说是可读性的改进)。呃,从NodeV6开始,导出/导入语法仍然不受支持。这里我们讨论的是非transpiled node.js,而不是一般意义上的ES2015。您对导出模块的看法如何。导出=(a,b)=>{return a+b}意味着箭头函数我将避免这种情况。我喜欢将commonjs语法与实际的实现代码分开。同样命名的函数有助于更好地进行堆栈跟踪,因此命名它们有助于调试。请注意,接受的答案和这个问题都非常古老,JS已经更新了导入/导出语句,这些语句可以提高性能和可读性,但在撰写本文时,当前已被接受的答案中并未涉及这些语句。@KyleBaker您能提供一个例子吗?我现在没有时间写出符合我标准的答案。然而,MDN有一些例子。目前可在此处进行深入勘探:
var foo = require("foo");
function doubleFoo(value) {
return foo(value) * 2;
}
function tripleFoo(value) {
return foo(value) * 3;
}
exports.doubleFoo = doubleFoo;
exports.tripleFoo = tripleFoo;
function GoCart() {
this.wheels = 4;
}
GoCart.prototype.drive = function drive() {
//vroom vroom
}
module.exports = GoCart;
//do-stuff.js
function doStuff(howFast, what) {
return "I am doing " + what + " at speed " + howFast;
}
function setup(options) {
//The object returned by this will have closure access to options
//for its entire lifetime
return {doStuff: doStuff.bind(null, options.howFast)};
}
module.exports = setup;
var doStuff = require("./do-stuff")({howFast: "blazing speed"});
console.log(doStuff.doStuff("jogging"));
//"I am doing jogging at speed blazing speed"