javascript - tutorial - require(' express ') in node js
In Node.js, come faccio a "includere" le funzioni dai miei altri file? (16)
Includi il file ed eseguilo in un determinato contesto (non globale)
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);
Diciamo che ho un file chiamato app.js. Abbastanza semplice:
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);
Cosa succede se ho una funzione all'interno di "tools.js". Come posso importarli per l'uso in apps.js?
Oppure ... dovrei trasformare "strumenti" in un modulo e quindi richiederlo? << sembra difficile, preferisco fare l'importazione di base del file tools.js.
App.js:
var mymouldle = require("C:/Users/Yourname/tools.js")
//replace C:/Users/Yourname/tools.js with the path to your tools.js
NOTA: il file deve iniziare con C: o D: o E: altrimenti Node.js pensa che il mouldle si trovi nella cartella dei mouldles del nodo
Crea due file js
// File cal.js
module.exports = {
sum: function(a,b) {
return a+b
},
multiply: function(a,b) {
return a*b
}
};
File js principale
// File app.js
var tools = require("./cal.js");
var value = tools.sum(10,20);
console.log("Value: "+value);
Produzione
value: 30
Ecco una spiegazione semplice e semplice:
Contenuto 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);
Contenuto 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 ()
{
};
Ho trovato un metodo piuttosto grezzo di gestione di questo per i template HTML. Analogamente a 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>
Risultato della pagina caricata
<!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>
Il modulo vm in Node.js offre la possibilità di eseguire codice JavaScript all'interno del contesto corrente (incluso l'oggetto globale). Vedi http://nodejs.org/docs/latest/api/vm.html#vm_vm_runinthiscontext_code_filename
Nota che, ad oggi, c'è un bug nel modulo vm che previene il runInThisContext dal fare il diritto quando viene invocato da un nuovo contesto. Ciò è importante solo se il tuo programma principale esegue il codice all'interno di un nuovo contesto e quindi il codice chiama runInThisContext. Vedi https://github.com/joyent/node/issues/898
Purtroppo, l'approccio (globale) suggerito da Fernando non funziona per funzioni denominate come "function foo () {}"
In breve, ecco una funzione include () che funziona per me:
function include(path) {
var code = fs.readFileSync(path, 'utf-8');
vm.runInThisContext(code, path);
}
Puoi mettere le tue funzioni in variabili globali, ma è meglio fare semplicemente girare lo script degli strumenti in un modulo. Non è davvero troppo difficile - basta allegare la tua API pubblica all'oggetto exports
. Dai un'occhiata al modulo delle esportazioni di Node.js per ulteriori dettagli.
Puoi richiedere qualsiasi file js, devi solo dichiarare ciò che vuoi esporre.
// tools.js
// ========
module.exports = {
foo: function () {
// whatever
},
bar: function () {
// whatever
}
};
var zemba = function () {
}
E nel tuo file dell'app:
// app.js
// ======
var tools = require('./tools');
console.log(typeof tools.foo); // => 'function'
console.log(typeof tools.bar); // => 'function'
console.log(typeof tools.zemba); // => undefined
Questo è il modo migliore che ho creato finora.
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();
Hai ancora bisogno di informare ciò che vuoi esportare
includeOnce('./bin/WebServer.js');
function Lara() {
this.webServer = new WebServer();
this.webServer.start();
}
Lara.prototype.webServer = null;
module.exports.Lara = Lara;
Se vuoi approfittare di più CPU e architettura di Microservice, per velocizzare le cose ... Usa gli RPC su processi biforcati.
Sembra complesso, ma è semplice se usi il octopus .
Ecco un esempio:
su tools.js aggiungi:
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;
});
su app.js, aggiungi:
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));
disclosure - Sono l'autore di octopus, e costruito per un mio simile pacchetto, dal momento che non sono riuscito a trovare alcuna libreria leggera.
Stavo anche cercando un'opzione per includere il codice senza scrivere moduli, resp. utilizzare le stesse sorgenti autonome testate da un progetto diverso per un servizio Node.js - e la risposta di lo ha fatto per me.
Il vantaggio è che non si inquina lo spazio dei nomi, non ho problemi con "use strict";
e funziona bene.
Ecco un esempio completo :
Script da caricare - /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'
}
}
Spero che questo sia stato utile in qualche modo.
Stavo anche cercando una funzione 'include' di NodeJS e ho controllato la soluzione proposta da Udo G - vedi messaggio https://.com/a/8744519/2979590 . Il suo codice non funziona con i miei file JS inclusi. Alla fine ho risolto il problema in questo modo:
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');
Certo, questo aiuta.
Un altro metodo quando si utilizza il framework node.js e express.js
var f1 = function(){
console.log("f1");
}
var f2 = function(){
console.log("f2");
}
module.exports = {
f1 : f1,
f2 : f2
}
memorizzarlo in un file js denominato s e nella cartella statica
Ora per usare la funzione
var s = require('../statics/s');
s.f1();
s.f2();
Un altro modo per farlo a mio parere è eseguire tutto nel file lib quando chiamate funzione require () usando (function (/ * things here * /) {}) (); facendo questo si renderanno globali tutte queste funzioni, esattamente come la soluzione 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');
}
}
})();
E poi nel tuo codice principale puoi chiamare le tue funzioni per nome come:
main.js
require('./src/lib')
funcOne();
funcThree('Alex');
console.log(name);
console.log(myobject);
console.log(myobject.funcFour());
Farà questa uscita
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
Prestare attenzione al non definito quando si chiama il mio oggetto.funcFour () , sarà lo stesso se si carica con eval () . Spero che sia d'aiuto :)
diciamo che vogliamo chiamare function ping () e add (30,20) che è nel file lib.js da 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
}
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 };