Caricare ed eseguire il file js esterno in node.js con accesso alle variabili locali?


130

È facile / possibile eseguire un semplice include('./path/to/file')tipo di comando in node.js?

Tutto quello che voglio fare è avere accesso alle variabili locali ed eseguire uno script. In che modo le persone organizzano in genere progetti node.js che sono più grandi di un semplice mondo? (Un sito Web dinamico completamente funzionale)

Ad esempio, vorrei avere directory come:

/models

/views

... eccetera


È anche possibile includere uno script da un URL esterno (anziché un file locale). Vedi qui: pastebin.com/WkvHjGsG
Anderson Green

Lo script sopra funziona correttamente solo se crei una cartella chiamata downloadedModulesnella stessa directory dello script.
Anderson Green

Risposte:


134

Basta fare un require('./yourfile.js');

Dichiarare tutte le variabili a cui si desidera accedere all'esterno come variabili globali. Quindi invece di

var a = "hello" sarà

GLOBAL.a="hello" o solo

a = "hello"

Questo è ovviamente negativo. Non vuoi inquinare l'ambito globale. Invece il metodo suggerito è per le exporttue funzioni / variabili.

Se vuoi il modello MVC dai un'occhiata a Geddy.


3
Come nota a margine ... adoro Express. Dovresti anche verificarlo, a condizione che tu non sia così particolare su MVC.
Shripad Krishna,

43
Quando dici "questo è ovviamente negativo", a cosa si riferisce "questo"?
Anderson Green,

1
@AndersonGreen - Intende mettere le variabili in ambito globale.
Tim

77
@AndersonGreen: Per favore, dimmi che è stata una battuta estremamente intelligente riguardo allo scoping ;-)
Dusty J

6
Mi ha aiutato a imparare che requireappare nei tuoi moduli npm se non aggiungi un prefisso al tuo percorso con qualcosa del tipo./
Dylan Valade,

93

È necessario comprendere CommonJS, che è un modello per definire i moduli. Non dovresti abusare dell'ambito GLOBAL che è sempre una brutta cosa da fare, invece puoi usare il token 'export', in questo modo:

// circle.js

var PI = 3.14; // PI will not be accessible from outside this module

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

E il codice client che utilizzerà il nostro modulo:

// client.js

var circle = require('./circle');
console.log( 'The area of a circle of radius 4 is '
           + circle.area(4));

Questo codice è stato estratto dall'API di documentazione node.js:

http://nodejs.org/docs/v0.3.2/api/modules.html

Inoltre, se vuoi usare qualcosa come Rails o Sinatra, ti consiglio Express (non potrei pubblicare l'URL, peccato su Stack Overflow!)


64

Se stai scrivendo codice per Node, usare i moduli Node come descritto da Ivan è senza dubbio la strada da percorrere.

Tuttavia, se è necessario caricare JavaScript che è già stato scritto e non è a conoscenza del nodo, il vmmodulo è la strada da percorrere (e sicuramente preferibileeval ).

Ad esempio, ecco il mio execfilemodulo, che valuta lo script pathin uno dei due contexto nel contesto globale:

var vm = require("vm");
var fs = require("fs");
module.exports = function(path, context) {
  var data = fs.readFileSync(path);
  vm.runInNewContext(data, context, path);
}

Nota anche: i moduli caricati con require(…)non hanno accesso al contesto globale.


1
Grazie per il consiglio. Il vero caso d'uso è quando è necessario caricare i moduli ad hoc. Dì come un modello di registrazione in cui avresti 1000 moduli che si registrano in un servizio centrale. È molto più pulito e meglio progettare scansionare i moduli e caricarli uno per uno piuttosto che fare 1000 dichiarazioni richieste al tuo servizio ...
Assaf Moldavsky

Il nodo supporta i requisiti dinamici, quindi non c'è motivo di utilizzare questo modello quando si caricano dinamicamente moduli sensibili al nodo. In effetti, è attivamente dannoso da utilizzare lì, poiché ignora i nodi require.cache, quindi un singolo file può essere caricato più volte.
David Wolever,

Ok, quindi per risolvere il caso che ho presentato in cui hai 1000 moduli in cui ognuno si sta registrando in un servizio di registro, come usi ciò che hai proposto senza avere 1000 istruzioni richieste nel servizio di registro?
Assaf Moldavsky,

1
Proprio requirecome normale: function loadService(name) { return require('./services/' + name); }quindi elencare i servizi ha comunque senso per l'applicazione.
David Wolever,

Giusto, ma ciò implica che devi conoscere tutti i 1000 moduli nel servizio di registro. Il che non è meglio che avere un 1000 richiede dichiarazioni. L'idea è che il servizio di registro non conosca tutti i moduli e in effetti se ne preoccupa. I moduli si registrano ad hoc nel servizio di registro. Ha senso?
Assaf Moldavsky,

7

Se stai pianificando di caricare le funzioni o gli oggetti di un file javascript esterno, carica su questo contesto usando il codice seguente: nota il metodo runInThisContext:

var vm = require("vm");
var fs = require("fs");

var data = fs.readFileSync('./externalfile.js');
const script = new vm.Script(data);
script.runInThisContext();

// here you can use externalfile's functions or objects as if they were instantiated here. They have been added to this context. 

2
Dopo molta ricerca e frobbing, questa tecnica ha funzionato per me. I miei file sono scritti per essere utilizzati direttamente dal browser e dichiarare una variabile, ad esempio: const aVar = {thing: 'a'}
lucsan,

3

In espansione @Shripad 's e @Ivan risposta' s, mi sento di raccomandare che si utilizza di serie di Node.js module.export funzionalità.

Nel tuo file per le costanti ( ad esempio constants.js ), dovresti scrivere costanti come questa:

const CONST1 = 1;
module.exports.CONST1 = CONST1;

const CONST2 = 2;
module.exports.CONST2 = CONST2;

Quindi nel file in cui si desidera utilizzare quelle costanti, scrivere il seguente codice:

const {CONST1 , CONST2} = require('./constants.js');

Se non hai mai visto la const { ... }sintassi prima: questo è un compito distruttivo .


0

Ci scusiamo per la risurrezione. È possibile utilizzare il modulo child_process per eseguire file js esterni in node.js

var child_process = require('child_process');

//EXECUTE yourExternalJsFile.js
child_process.exec('node yourExternalJsFile.js', (error, stdout, stderr) => {
    console.log(`${stdout}`);
    console.log(`${stderr}`);
    if (error !== null) {
        console.log(`exec error: ${error}`);
    }
});
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.