In Node.js, how do I “include” functions from my other files?
假设我有一个名为app.js的文件。很简单:
1 2 3 4 5 6 7 8 9 10 11 | var express = require('express'); var app = express.createServer(); app.set('views', __dirname + '/views'); app.set('view engine', 'ejs'); app.get('/', function(req, res){ res.render('index', {locals: { title: 'NowJS + Express Example' }}); }); app.listen(8080); |
如果我在"tools.js"中有一个函数怎么办?如何导入它们以在apps.js中使用?
或者…我应该把"工具"变成一个模块,然后需要它吗?<<似乎很难,我宁愿做tools.js文件的基本导入。
您可以需要任何JS文件,只需声明您想要公开的内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 | // tools.js // ======== module.exports = { foo: function () { // whatever }, bar: function () { // whatever } }; var zemba = function () { } |
在应用程序文件中:
1 2 3 4 5 6 | // app.js // ====== var tools = require('./tools'); console.log(typeof tools.foo); // => 'function' console.log(typeof tools.bar); // => 'function' console.log(typeof tools.zemba); // => undefined |
如果尽管有其他所有答案,但您仍然希望传统上在node.js源文件中包含一个文件,则可以使用此选项:
1 2 3 4 | var fs = require('fs'); // file is included here: eval(fs.readFileSync('tools.js')+''); |
- 空字符串连接
+'' 是获取文件内容作为字符串而不是对象所必需的(如果愿意,也可以使用.toString() )。 - eval()不能在函数内部使用,必须在全局范围内调用,否则将无法访问任何函数或变量(即不能创建
include() 实用函数或类似的函数)。
请注意,在大多数情况下,这是不好的做法,您应该编写一个模块。但是,很少有情况下,您真正想要的是本地上下文/名称空间的污染。
更新2015-08-06请注意,这对
您不需要新功能或新模块。如果不想使用名称空间,只需执行正在调用的模块。
在工具S. JS中1 2 3 4 5 | module.exports = function() { this.sum = function(a,b) { return a+b }; this.multiply = function(a,b) { return a*b }; //etc } |
在App.JS中
或者在其他任何.js中,比如mycontroller.js:
而不是
我们可以打电话
1 | require('tools.js')(); |
然后
1 | sum(1,2); |
在我的例子中,我有一个带有controllers ctrls.js的文件
1 2 3 | module.exports = function() { this.Categories = require('categories.js'); } |
我可以在每个上下文中使用
创建两个JS文件
1 2 3 4 5 6 7 8 9 | // File cal.js module.exports = { sum: function(a,b) { return a+b }, multiply: function(a,b) { return a*b } }; |
主JS文件
1 2 3 4 | // File app.js var tools = require("./cal.js"); var value = tools.sum(10,20); console.log("Value:"+value); |
产量
1 | value: 30 |
下面是一个简单明了的解释:
server.js内容:1 2 3 4 5 6 7 8 9 | // Include the public functions from 'helpers.js' var helpers = require('./helpers'); // Let's assume this is the data which comes from the database or somewhere else var databaseName = 'Walter'; var databaseSurname = 'Heisenberg'; // Use the function from 'helpers.js' in the main file, which is server.js var fullname = helpers.concatenateNames(databaseName, databaseSurname); |
helpers.js内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // 'module.exports' is a node.JS specific feature, it does not work with regular JavaScript module.exports = { // This is the function which will be called in the main file, which is server.js // The parameters 'name' and 'surname' will be provided inside the function // when the function is called in the main file. // Example: concatenameNames('John,'Doe'); concatenateNames: function (name, surname) { var wholeName = name +"" + surname; return wholeName; }, sampleFunctionTwo: function () { } }; // Private variables and functions which will not be accessible outside this file var privateFunction = function () { }; |
我还在寻找nodejs的"include"函数,我检查了udo g提出的解决方案-参见消息https://stackoverflow.com/a/8744519/2979590。他的代码不适用于我包含的JS文件。最后我解决了这样的问题:
1 2 3 4 5 6 7 8 9 10 | var fs = require("fs"); function read(f) { return fs.readFileSync(f).toString(); } function include(f) { eval.apply(global, [read(f)]); } include('somefile_with_some_declarations.js'); |
当然,这有帮助。
node.js中的vm模块提供在当前上下文(包括全局对象)中执行javascript代码的能力。请参见http://nodejs.org/docs/latest/api/vm.html vm vm runinthiscoxt code filename
注意,从今天开始,VM模块中存在一个bug,它阻止Runin上下文从新上下文调用时做正确的操作。只有当主程序在新的上下文中执行代码,然后该代码调用RunIn上下文时,这才是重要的。参见HTTPS:/GIHUUBCOM/JONTEN/NODE/SUNES/898
遗憾的是,费尔南多建议的使用(全局)方法对于命名函数"函数脚"({})不起作用。
简而言之,这里有一个为我工作的包含函数。
1 2 3 4 | function include(path) { var code = fs.readFileSync(path, 'utf-8'); vm.runInThisContext(code, path); } |
假设我们想调用函数ping()并添加(30,20),它在lib.js文件中从M.J.
MIN JS
1 2 3 4 5 6 7 | lib = require("./lib.js") output = lib.ping(); console.log(output); //Passing Parameters console.log("Sum of A and B =" + lib.add(20,30)) |
LIB JS
1 2 3 4 | this.ping=function () { return "Ping Success" } |
1 2 3 4 5 | //Functions with parameters this.add=function(a,b) { return a+b } |
Udo G.说:
- The eval() can't be used inside a function and must be called inside
the global scope otherwise no functions or variables will be
accessible (i.e. you can't create a include() utility function or
something like that).
他是对的,但有一种方法可以从一个函数影响全局范围。改进他的例子:
1 2 3 4 5 6 7 8 9 | function include(file_) { with (global) { eval(fs.readFileSync(file_) + ''); }; }; include('somefile_with_some_declarations.js'); // the declarations are now accessible here. |
希望,这有帮助。
在我看来,另一种方法是在使用(function(/*things here*/))()调用require()函数时执行lib文件中的所有内容;这样做将使所有这些函数成为全局范围,与eval()解决方案完全相同。
SRC/LIB JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | (function () { funcOne = function() { console.log('mlt funcOne here'); } funcThree = function(firstName) { console.log(firstName, 'calls funcThree here'); } name ="Mulatinho"; myobject = { title: 'Node.JS is cool', funcFour: function() { return console.log('internal funcFour() called here'); } } })(); |
然后,在主代码中,您可以通过以下名称调用函数:
MIN JS
1 2 3 4 5 6 | require('./src/lib') funcOne(); funcThree('Alex'); console.log(name); console.log(myobject); console.log(myobject.funcFour()); |
将生成此输出
1 2 3 4 5 6 7 8 9 | bash-3.2$ node -v v7.2.1 bash-3.2$ node main.js mlt funcOne here Alex calls funcThree here Mulatinho { title: 'Node.JS is cool', funcFour: [Function: funcFour] } internal funcFour() called here undefined |
当调用my object.funcfur()时,请注意未定义的,如果使用eval()加载,它将是相同的。希望有帮助:)
您可以将函数放在全局变量中,但最好将工具脚本转换为模块。这并不太难——只需将公共API连接到
我只是想补充一点,如果您只需要从tools.js导入某些函数,那么您可以使用自6.4版以来node.js支持的破坏性赋值——请参见node.green。
例子:(两个文件在同一文件夹中)
tools.js
1 2 3 4 5 6 7 8 | module.exports = { sum: function(a,b) { return a + b; }, isEven: function(a) { return a % 2 == 0; } }; |
main.js
1 2 3 | const { isEven } = require('./tools.js'); console.log(isEven(10)); |
输出:
这也避免了在以下(公共)分配中,将这些函数作为另一个对象的属性进行分配:
你需要打电话给
注:
别忘了在文件名前面加上正确的路径——即使两个文件都在同一个文件夹中,也需要在文件名前面加上EDOCX1[12]
从node.js文档:
Without a leading '/', './', or '../' to indicate a file, the module
must either be a core module or is loaded from a node_modules folder.
它对我起到了如下作用…
LIB 1.JS
1 2 3 4 5 6 7 | //Any other private code here // Code you want to export exports.function1 = function1 (params) {.......}; exports.function2 = function2 (params) {.......}; // Again any private code |
现在在main.js文件中,您需要包含lib1.js
1 2 3 | var mylib = requires('lib1.js'); mylib.function1(params); mylib.function2(params); |
请记住将lib1.js放在node_modules文件夹中。
App.JS
1 2 | let { func_name } = require('path_to_tools.js'); func_name(); //function calling |
JS工具
1 2 3 4 5 6 7 | let func_name = function() { ... //function body ... }; module.exports = { func_name }; |
包含文件并在给定(非全局)上下文中运行它文件包含.js
1 2 3 | define({ "data":"XYZ" }); |
MIN JS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var fs = require("fs"); var vm = require("vm"); function include(path, context) { var code = fs.readFileSync(path, 'utf-8'); vm.runInContext(code, vm.createContext(context)); } // Include file var customContext = { "define": function (data) { console.log(data); } }; include('./fileToInclude.js', customContext); |
就像你有一个文件一样,还有更多吗?
创建2个文件:
1 2 3 4 5 6 7 8 9 10 11 12 | function fileread(filename) { var contents= fs.readFileSync(filename); return contents; } var fs = require("fs"); // file system //var data = fileread("abc.txt"); module.exports.fileread = fileread; //data.say(); //console.log(data.toString()); } |
在
1 2 3 4 5 6 7 8 9 10 11 12 13 | function myerror(){ console.log("Hey need some help"); console.log("type file=abc.txt"); } var ags = require("minimist")(process.argv.slice(2), { string:"file" }); if(ags.help || !ags.file) { myerror(); process.exit(1); } var hello = require("./fileread.js"); var data = hello.fileread(ags.file); // importing module here console.log(data.toString()); |
现在,在终端中:$node fetchingfile.js--文件=abc.txt
您正在将文件名作为参数传递,而且还包括
谢谢
这是我迄今为止创造的最好的方式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | var fs = require('fs'), includedFiles_ = {}; global.include = function (fileName) { var sys = require('sys'); sys.puts('Loading file: ' + fileName); var ev = require(fileName); for (var prop in ev) { global[prop] = ev[prop]; } includedFiles_[fileName] = true; }; global.includeOnce = function (fileName) { if (!includedFiles_[fileName]) { include(fileName); } }; global.includeFolderOnce = function (folder) { var file, fileName, sys = require('sys'), files = fs.readdirSync(folder); var getFileName = function(str) { var splited = str.split('.'); splited.pop(); return splited.join('.'); }, getExtension = function(str) { var splited = str.split('.'); return splited[splited.length - 1]; }; for (var i = 0; i < files.length; i++) { file = files[i]; if (getExtension(file) === 'js') { fileName = getFileName(file); try { includeOnce(folder + '/' + file); } catch (err) { // if (ext.vars) { // console.log(ext.vars.dump(err)); // } else { sys.puts(err); // } } } } }; includeFolderOnce('./extensions'); includeOnce('./bin/Lara.js'); var lara = new Lara(); |
你仍然需要告知你想要出口什么
1 2 3 4 5 6 7 8 9 10 | includeOnce('./bin/WebServer.js'); function Lara() { this.webServer = new WebServer(); this.webServer.start(); } Lara.prototype.webServer = null; module.exports.Lara = Lara; |
你只需简单地输入
如。
1 2 3 4 5 6 7 8 9 10 11 | // file: index.js var express = require('express'); var app = express(); var child = require('./child'); app.use('/child', child); app.get('/', function (req, res) { res.send('parent'); }); app.listen(process.env.PORT, function () { console.log('Example app listening on port '+process.env.PORT+'!'); }); |
1 2 3 4 5 6 7 8 9 10 11 12 | // file: child.js var express = require('express'), child = express.Router(); console.log('child'); child.get('/child', function(req, res){ res.send('Child2'); }); child.get('/', function(req, res){ res.send('Child'); }); module.exports = child; |
请注意:
使用node.js和express.js框架时的另一种方法
1 2 3 4 5 6 7 8 9 10 11 | var f1 = function(){ console.log("f1"); } var f2 = function(){ console.log("f2"); } module.exports = { f1 : f1, f2 : f2 } |
将其存储在名为s的JS文件和statics文件夹中
现在使用函数
1 2 3 | var s = require('../statics/s'); s.f1(); s.f2(); |
我想出了一个相当粗糙的方法来处理HTML模板化。与php
server.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var fs = require('fs'); String.prototype.filter = function(search,replace){ var regex = new RegExp("{{" + search.toUpperCase() +"}}","ig"); return this.replace(regex,replace); } var navigation = fs.readFileSync(__dirname +"/parts/navigation.html"); function preProcessPage(html){ return html.filter("nav",navigation); } var express = require('express'); var app = express(); // Keep your server directory safe. app.use(express.static(__dirname + '/public/')); // Sorta a server-side .htaccess call I suppose. app.get("/page_name/",function(req,res){ var html = fs.readFileSync(__dirname +"/pages/page_name.html"); res.send(preProcessPage(html)); }); |
page_name.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> NodeJS Templated Page <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css"> <!-- Scripts Load After Page --> <script type="text/javascript" src="/js/jquery.min.js"> <script type="text/javascript" src="/js/tether.min.js"> <script type="text/javascript" src="/js/bootstrap.min.js"> </head> <body> {{NAV}} <!-- Page Specific Content Below Here--> </body> </html> |
navigation.html
1 | <nav></nav> |
Loaded Page Result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> NodeJS Templated Page <link rel="stylesheet" type="text/css" href="/css/bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="/css/font-awesome.min.css"> <!-- Scripts Load After Page --> <script type="text/javascript" src="/js/jquery.min.js"> <script type="text/javascript" src="/js/tether.min.js"> <script type="text/javascript" src="/js/bootstrap.min.js"> </head> <body> <nav></nav> <!-- Page Specific Content Below Here--> </body> </html> |
我也在寻找一个不需要编写模块就可以包含代码的选项。对node.js服务使用来自不同项目的相同测试的独立源,jmpartates的答案为我做了这件事。
其好处是,您不会污染名称空间,我对
这里是一个完整的样本:
要加载的脚本-/lib/foo.js1 2 3 4 5 6 7 8 9 10 11 12 13 | "use strict"; (function(){ var Foo = function(e){ this.foo = e; } Foo.prototype.x = 1; return Foo; }()) |
示例模块-index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | "use strict"; const fs = require('fs'); const path = require('path'); var SampleModule = module.exports = { instAFoo: function(){ var Foo = eval.apply( this, [fs.readFileSync(path.join(__dirname, '/lib/foo.js')).toString()] ); var instance = new Foo('bar'); console.log(instance.foo); // 'bar' console.log(instance.x); // '1' } } |
希望这能有所帮助。
如果您想利用多个CPU和微服务体系结构,以加快速度……请使用RPC而不是分叉进程。
听起来很复杂,但使用章鱼很简单。
下面是一个例子:
在tools.js上添加:
1 2 3 4 5 6 7 8 9 10 | const octopus = require('octopus'); var rpc = new octopus('tools:tool1'); rpc.over(process, 'processRemote'); var sum = rpc.command('sum'); // This is the example tool.js function to make available in app.js sum.provide(function (data) { // This is the function body return data.a + data.b; }); |
关于App.js,添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const { fork } = require('child_process'); const octopus = require('octopus'); const toolprocess = fork('tools.js'); var rpc = new octopus('parent:parent1'); rpc.over(toolprocess, 'processRemote'); var sum = rpc.command('sum'); // Calling the tool.js sum function from app.js sum.call('tools:*', { a:2, b:3 }) .then((res)=>console.log('response : ',rpc.parseResponses(res)[0].response)); |
披露-我是章鱼的作者,如果我找不到任何轻量级的图书馆,那么我就要为我的类似用途建造它。
用途:
1 | var mymodule = require("./tools.js") |
App.JS:
1 2 3 | module.exports.<your function> = function () { <what should the function do> } |