簡體   English   中英

在 Node.js 中,如何從我的其他文件中“包含”函數?

[英]In Node.js, how do I "include" functions from my other files?

假設我有一個名為 app.js 的文件。 很簡單:

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 文件,你只需要聲明你想要公開的內容。

// tools.js
// ========
module.exports = {
  foo: function () {
    // whatever
  },
  bar: function () {
    // whatever
  }
};

var zemba = function () {
}

在您的應用程序文件中:

// 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 源文件中包含一個文件,您可以使用以下命令:

var fs = require('fs');

// file is included here:
eval(fs.readFileSync('tools.js')+'');
  • 空字符串連接+''是獲取文件內容作為字符串而不是對象所必需的.toString()如果您願意,也可以使用.toString() )。
  • eval() 不能在函數內部使用,必須在全局范圍內調用,否則將無法訪問任何函數或變量(即您不能創建include()實用程序函數或類似的東西)。

請注意,在大多數情況下,這是不好的做法,您應該編寫一個模塊 但是,在極少數情況下,您真正​​想要的是本地上下文/命名空間的污染。

更新 2015-08-06

另請注意,這不適用於"use strict"; (當您處於“嚴格模式”時),因為執行導入的代碼無法訪問“導入”文件中定義的函數和變量。 嚴格模式強制執行由較新版本的語言標准定義的一些規則。 這可能是避免此處描述的解決方案的另一個原因。

您不需要新功能或新模塊。 如果您不想使用命名空間,您只需要執行您正在調用的模塊。

在 tools.js 中

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 :

代替

var tools = require('tools.js')這迫使我們使用命名空間並調用tools.sum(1,2);類的工具tools.sum(1,2);

我們可以簡單地調用

require('tools.js')();

進而

sum(1,2);

就我而言,我有一個帶有控制器ctrls.js的文件

module.exports = function() {
    this.Categories = require('categories.js');
}

require('ctrls.js')()之后,我可以在每個上下文中使用Categories作為公共類

創建兩個js文件

// File cal.js
module.exports = {
    sum: function(a,b) {
        return a+b
    },
    multiply: function(a,b) {
        return a*b
    }
};

主js文件

// File app.js
var tools = require("./cal.js");
var value = tools.sum(10,20);
console.log("Value: "+value);

控制台輸出

Value: 30

創建兩個文件,例如app.jstools.js

應用程序.js

const tools= require("./tools.js")


var x = tools.add(4,2) ;

var y = tools.subtract(4,2);


console.log(x);
console.log(y);

工具.js

 const add = function(x, y){
        return x+y;
    }
 const subtract = function(x, y){
            return x-y;
    }
    
    module.exports ={
        add,subtract
    }

輸出

6
2

這是一個簡單明了的解釋:

Server.js 內容:

// 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 內容:

// '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 文件。 最后我解決了這樣的問題:

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');

當然,這有幫助。

創建兩個 JavaScript 文件。 例如import_functions.jsmain.js

1.) import_functions.js

// Declaration --------------------------------------

 module.exports =
   {
     add,
     subtract
     // ...
   }


// Implementation ----------------------------------

 function add(x, y)
 {
   return x + y;
 }

 function subtract(x, y)
 {
   return x - y;
 }
    

// ...

2.) main.js

// include ---------------------------------------

const sf= require("./import_functions.js")

// use -------------------------------------------

var x = sf.add(4,2);
console.log(x);

var y = sf.subtract(4,2);
console.log(y);

    

輸出

6
2

Node.js 中的 vm 模塊提供了在當前上下文(包括全局對象)中執行 JavaScript 代碼的能力。 http://nodejs.org/docs/latest/api/vm.html#vm_vm_runinthiscontext_code_filename

請注意,截至今天,vm 模塊中存在一個錯誤,該錯誤阻止 runInThisContext 在從新上下文調用時執行正確的操作。 這僅在您的主程序在新上下文中執行代碼然后該代碼調用 runInThisContext 時才重要。 https://github.com/joyent/node/issues/898

遺憾的是,Fernando 建議的 with(global) 方法不適用於諸如“function foo() {}”之類的命名函數

簡而言之,這是一個對我有用的 include() 函數:

function include(path) {
    var code = fs.readFileSync(path, 'utf-8');
    vm.runInThisContext(code, path);
}

假設我們想從main.js 調用lib.js文件中的函數ping()add(30,20)

主文件

lib = require("./lib.js")

output = lib.ping();
console.log(output);

//Passing Parameters
console.log("Sum of A and B = " + lib.add(20,30))

庫.js

this.ping=function ()
{
    return  "Ping Success"
}
//Functions with parameters
this.add=function(a,b)
    {
        return a+b
    }

Udo G. 說:

  • eval() 不能在函數內部使用,必須在全局范圍內調用,否則將無法訪問任何函數或變量(即您不能創建 include() 實用程序函數或類似的東西)。

他是對的,但是有一種方法可以從函數中影響全局范圍。 改進他的例子:

function include(file_) {
    with (global) {
        eval(fs.readFileSync(file_) + '');
    };
};

include('somefile_with_some_declarations.js');

// the declarations are now accessible here.

希望,這有幫助。

它與我一起工作,如下所示......

Lib1.js

//Any other private code here 

// Code you want to export
exports.function1 = function(params) {.......};
exports.function2 = function(params) {.......};

// Again any private code

現在在Main.js文件中,您需要包含Lib1.js

var mylib = requires('lib1.js');
mylib.function1(params);
mylib.function2(params);

請記住將 Lib1.js 放在node_modules 文件夾中

在我看來,另一種方法是在調用require()函數時執行 lib 文件中的所有內容(function(/* things here */){})(); 這樣做將使所有這些函數成為全局范圍,就像eval()解決方案一樣

源代碼/庫.js

(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');
            }
    }
})();

然后在您的主代碼中,您可以按名稱調用您的函數,例如:

主文件

require('./src/lib')
funcOne();
funcThree('Alex');
console.log(name);
console.log(myobject);
console.log(myobject.funcFour());

將使這個輸出

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

當你調用我的object.funcFour()時注意undefined ,如果你用eval()加載它也會一樣。 希望能幫助到你 :)

應用程序.js

let { func_name } = require('path_to_tools.js');
func_name();    //function calling

工具.js

let func_name = function() {
    ...
    //function body
    ...
};

module.exports = { func_name };

我只想補充一點,如果您只需要從tools.js導入某些函數,那么您可以使用自6.4版起在 node.js 中支持的解構賦值- 請參閱node.green


示例:(兩個文件都在同一個文件夾中)

工具.js

module.exports = {
    sum: function(a,b) {
        return a + b;
    },
    isEven: function(a) {
        return a % 2 == 0;
    }
};

主文件

const { isEven } = require('./tools.js');

console.log(isEven(10));

輸出: true


這也避免了您將這些函數分配為另一個對象的屬性,就像在以下(常見)分配中的情況一樣:

const tools = require('./tools.js');

你需要在那里調用tools.isEven(10)


筆記:

不要忘記使用正確的路徑作為文件名的前綴 - 即使兩個文件都在同一個文件夾中,您也需要使用./

來自Node.js 文檔

如果沒有前導 '/'、'./' 或 '../' 來指示文件,則該模塊必須是核心模塊或從 node_modules 文件夾加載。

您可以將您的函數放在全局變量中,但更好的做法是將您的工具腳本變成一個模塊。 這真的不是太難 - 只需將您的公共 API 附加到exports對象。 查看了解 Node.js 的導出模塊以獲取更多詳細信息。

包含文件並在給定(非全局)上下文中運行它

fileToInclude.js

define({
    "data": "XYZ"
});

主文件

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);

使用 ESM 模塊系統:

a.js

export default function foo() {};

export function bar() {};

b.js

import foo, {bar} from './a.js';

這是我迄今為止創建的最佳方式。

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();

您仍然需要告知您要導出的內容

includeOnce('./bin/WebServer.js');

function Lara() {
  this.webServer = new WebServer();
  this.webServer.start();
}

Lara.prototype.webServer = null;

module.exports.Lara = Lara;

我想出了一種相當粗糙的方法來處理HTML模板。 類似於PHP <?php include("navigation.html"); ?> <?php include("navigation.html"); ?>

server.js

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>NodeJS Templated Page</title>
    <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>
    <script type="text/javascript" src="/js/tether.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap.min.js"></script>
</head>
<body>
    {{NAV}}
    <!-- Page Specific Content Below Here-->
</body>
</html>

navigation.html

<nav></nav>

載入頁面結果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>NodeJS Templated Page</title>
    <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>
    <script type="text/javascript" src="/js/tether.min.js"></script>
    <script type="text/javascript" src="/js/bootstrap.min.js"></script>
</head>
<body>
    <nav></nav>
    <!-- Page Specific Content Below Here-->
</body>
</html>

Node 基於 commonjs 模塊和最近的 esm 模塊工作。 基本上,您應該在 separated.js 文件中創建模塊並使用導入/導出(module.exports 和 require)。

Javascript 在瀏覽器上的工作方式不同,基於 scope。有全局 scope,通過 clojures(其他函數中的函數)你有私有范圍。

因此,在節點中,導出您將在其他模塊中使用的函數和對象。

IMO 最干凈的方法如下,在 tools.js 中:

function A(){
.
.
.
}

function B(){
.
.
.
}

module.exports = {
A,
B
}

然后,在 app.js 中,只需要 tools.js 如下: const tools = require("tools");

我也在尋找一個選項來包含代碼而不編寫模塊,resp。 對 Node.js 服務使用來自不同項目的相同經過測試的獨立源代碼 - jmparatte的回答為我做到了。

好處是,你不會污染命名空間,我沒有"use strict";麻煩"use strict"; 它運作良好。

這是一個完整的示例:

要加載的腳本 - /lib/foo.js

"use strict";

(function(){

    var Foo = function(e){
        this.foo = e;
    }

    Foo.prototype.x = 1;

    return Foo;

}())

示例模塊 - index.js

"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'
    }

}

希望這在某種程度上有所幫助。

就像你有一個文件abc.txt等等?

創建 2 個文件: fileread.jsfetchingfile.js ,然后在fileread.js編寫以下代碼:

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());
}

fetchingfile.js編寫以下代碼:

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 --file=abc.txt

您將文件名作為參數傳遞,而且在readfile.js包含所有文件而不是傳遞它。

謝謝

使用 node.js 和 express.js 框架時的另一種方法

var f1 = function(){
   console.log("f1");
}
var f2 = function(){
   console.log("f2");
}

module.exports = {
   f1 : f1,
   f2 : f2
}

將其存儲在名為 s 的 js 文件和文件夾 statics 中

現在使用該功能

var s = require('../statics/s');
s.f1();
s.f2();

您可以簡單地使用require('./filename')

例如。

// 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+'!');
});
// 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;

請注意:

  1. 您不能在子文件上偵聽 PORT,只有父 Express 模塊具有 PORT 偵聽器
  2. 孩子正在使用“路由器”,而不是父 Express 模塊。

如果您想利用多個CPU和微服務體系結構來加快處理速度,請在分叉進程上使用RPC。

聽起來很復雜,但是使用章魚很簡單。

這是一個例子:

在tools.js上添加:

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上,添加:

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));

披露-我是章魚的作者,並且為我的類似用例而構建,因為我找不到任何輕量級的庫。

把“工具”變成一個模塊,我覺得一點也不難。 盡管有所有其他答案,我仍然建議使用 module.exports:

//util.js
module.exports = {
   myFunction: function () {
   // your logic in here
   let message = "I am message from myFunction";
   return message; 
  }
}

現在我們需要將此導出分配給全局范圍(在您的 app|index|server.js 中)

var util = require('./util');

現在您可以將函數引用和調用為:

//util.myFunction();
console.log(util.myFunction()); // prints in console :I am message from myFunction 

要在 Unix 環境中以交互方式測試模塊./test.js ,可以使用這樣的方法:

    >> node -e "eval(''+require('fs').readFileSync('./test.js'))" -i
    ...

用:

var mymodule = require("./tools.js")

應用程序.js:

module.exports.<your function> = function () {
    <what should the function do>
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM