В Node.js, как мне включить функции из других файлов?

Скажем, у меня есть файл под названием 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.

Ответы

Ответ 1

Вам может потребоваться любой файл 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

Ответ 2

Если, несмотря на все остальные ответы, вы по-прежнему хотите традиционно включать файл в исходный файл node.js, вы можете использовать это:

var fs = require('fs');

// file is included here:
eval(fs.readFileSync('tools.js')+'');
  • Пустая конкатенация строк +'' необходима для получения содержимого файла как строки, а не объекта (вы также можете использовать .toString(), если хотите).
  • Функция eval() не может использоваться внутри функции и должна вызываться внутри глобальной области, иначе никакие функции или переменные не будут доступны (т.е. вы не можете создать служебную программу include() или что-то в этом роде).

Обратите внимание, что в большинстве случаев это плохая практика, и вместо этого вы должны написать модуль. Однако есть редкие ситуации, когда загрязнение вашего локального контекста/пространства имен является тем, что вы действительно хотите.

Обновление 2015-08-06

Также обратите внимание, что это не будет работать с "use strict"; (когда вы находитесь в "строгом режиме" ), поскольку функции и переменные, определенные в "импортированном" файле не может быть доступен кодом, который выполняет импорт. Строгий режим обеспечивает выполнение некоторых правил, определяемых новыми версиями языкового стандарта. Это может быть еще одной причиной, чтобы избежать описанного здесь решения.

Ответ 3

Вам не нужны новые функции и новые модули. Вам просто нужно выполнить модуль, который вы вызываете, если вы не хотите использовать пространство имен.

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

мы можем просто называть

require('tools.js')();

а затем

sum(1,2);

в моем случае у меня есть файл с контроллерами ctrls.js

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

и я могу использовать Categories в каждом контексте как открытый класс после require('ctrls.js')()

Ответ 4

Создайте два 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

Ответ 5

Вот простое и простое объяснение:

Содержимое Server.js:

// Include the public functions from 'helpers.js'
var helpers = require('./helpers');

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

Ответ 6

Я также искал функцию NodeJS 'include', и я проверил решение, предложенное Udo G - см. сообщение fooobar.com/questions/13270/..., Его код не работает с моими включенными файлами 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');

Конечно, это помогает.

Ответ 7

скажем, мы хотим вызвать функцию ping() и добавить (30,20), которая находится в файле lib.js от main.js

main.js

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

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

Ответ 8

Модуль vm в Node.js предоставляет возможность выполнять JavaScript-код в текущем контексте (включая глобальный объект). См. http://nodejs.org/docs/latest/api/vm.html#vm_vm_runinthiscontext_code_filename

Обратите внимание, что на сегодняшний день существует ошибка в модуле vm, которая предотвращает выполнение runInThisContext при вызове из нового контекста. Это имеет значение только в том случае, если ваша основная программа выполняет код в новом контексте, а затем этот код вызывает runInThisContext. См. https://github.com/joyent/node/issues/898

К сожалению, с (глобальным) подходом, предложенным Фернандо, не работает для названных функций, таких как function foo() {} "

Короче говоря, здесь функция include(), которая работает для меня:

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

Ответ 9

Удо Г. сказал:

  • Функция eval() не может использоваться внутри функции и должна быть вызвана внутри глобальная область, иначе никакие функции или переменные не будут (т.е. вы не можете создать служебную функцию include() или что-то подобное).

Он прав, но есть способ повлиять на глобальный масштаб от функции. Улучшение его примера:

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

include('somefile_with_some_declarations.js');

// the declarations are now accessible here.

Надеюсь, это поможет.

Ответ 10

Вы можете поместить свои функции в глобальные переменные, но лучше просто превратить ваш скрипт инструментов в модуль. Это на самом деле не так уж сложно - просто прикрепите ваш публичный API к объекту exports. Взгляните на модуль экспорта в Understanding Node.js для более подробной информации.

Ответ 11

Другим способом сделать это, на мой взгляд, является выполнение всего в файле lib, когда вы вызываете функцию require(), используя (function (/* things here */) {} )(); сделает все эти функции глобальной областью, точно так же, как решение eval()

SRC/lib.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');
            }
    }
})();

И затем в вашем основном коде вы можете вызвать свои функции по имени, например:

main.js

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

Обратите внимание на undefined, когда вы вызываете мой object.funcFour(), это будет то же самое, если вы загружаете eval(). Надеюсь, это поможет:)

Ответ 12

Это работало со мной как следующее....

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.

Ответ 13

Я просто хочу добавить, что если вам нужны только определенные функции, импортированные из вашего tools.js, тогда вы можете использовать назначение деструктурирования, которое поддерживается в node.js начиная с версии 6.4 - см. Node.green.


Пример: (оба файла находятся в одной папке)

tools.js

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

main.js

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

console.log(isEven(10));

вывод: true


Это также позволяет избежать назначения этих функций в качестве свойств другого объекта, как в следующем (общем) назначении:

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

где вам нужно вызвать tools.isEven(10).


НОТА:

Не забудьте указать префикс вашего имени файла с правильным путем - даже если оба файла находятся в одной папке, вам нужно использовать префикс ./

Из документов Node.js:

Без начальных символов '/', './' или '../' для указания файла модуль должен быть основным модулем или загружаться из папки node_modules.

Ответ 14

app.js

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

tools.js

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

module.exports = { func_name };

Ответ 15

Попробуйте этот полный пример кода. Вам нужно включить этот файл с помощью метода require в app.js где вы хотите включить функции другого файла ex main.js, и этот файл должен предоставлять указанные функции, как в примере ниже.

app.js

const mainFile= require("./main.js")


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

var y =  mainFile.multiply(2,5); 
console.log(y);

main.js

const add = function(x, y){
    return x+y;
}
const multiply = function(x,y){
    return x*y;
}

module.exports ={
    add:add,
    multiply:multiply
}

выход

6
10

Ответ 16

Включить файл и запустить его в заданном (неглобальном) контексте

fileToInclude.js

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

main.js

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

Ответ 17

Это лучший способ, который я создал до сих пор.

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;

Ответ 18

Как у вас есть файл abc.txt и еще много?

Создайте 2 файла: fileread.js и fetchingfile.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 вместо его передачи.

Спасибо

Ответ 19

Вы можете просто просто require('./filename').

Eg.

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

Обратите внимание:

  • вы не можете прослушивать PORT в дочернем файле, только родительский экспресс-модуль имеет прослушиватель PORT
  • Ребенок использует "Router", а не родительский Express moudle.

Ответ 20

Я также искал вариант включения кода без написания модулей, соответственно. используйте те же проверенные автономные источники из другого проекта для службы Node.js - и jmparatte ответ сделал это для меня.

Преимущество в том, что вы не загрязняете пространство имен, у меня нет проблем с "use strict";, и он работает хорошо.

Здесь полный образец:

Script для загрузки -/lib/foo.js

"use strict";

(function(){

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

    Foo.prototype.x = 1;

    return Foo;

}())

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

}

Надеюсь, что это было полезно как-то.

Ответ 21

Другой метод при использовании node.js и express.js framework

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

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

сохранить это в файле js с именем s и в папке statics

Теперь, чтобы использовать функцию

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

Ответ 22

Я придумал довольно грубый метод обработки этого шаблона HTML. Аналогично PHP <?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>

Ответ 23

Я создал модуль для импорта сценариев, экспорта в файл и включения модуля извне node_modules.

https://www.npmjs.com/package/node-import

Надеюсь, это поможет. Спасибо!

Ответ 24

Если вы хотите использовать преимущества нескольких процессоров и микросервисной архитектуры, чтобы ускорить процесс... Используйте 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));

Раскрытие - я автор осьминога и создан для аналогичного варианта использования, так как не смог найти легких библиотек.

Ответ 25

Чтобы превратить "инструменты" в модуль, я не вижу ничего сложного. Несмотря на все остальные ответы, я все равно рекомендую использовать module.exports:

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

Теперь нам нужно назначить этот экспорт в глобальную область (в вашем приложении | index | server.js)

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

Теперь вы можете ссылаться и вызывать функцию как:

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

Ответ 26

Использование:

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

app.js:

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