Externe js-Datei in node.js mit Zugriff auf lokale Variablen laden und ausführen?


130

Ist es einfach / möglich, einen einfachen include('./path/to/file')Befehlstyp in node.js auszuführen?

Ich möchte nur auf lokale Variablen zugreifen und ein Skript ausführen. Wie organisieren Leute normalerweise node.js Projekte, die größer sind als eine einfache Hallo-Welt? (Eine voll funktionsfähige dynamische Website)

Zum Beispiel hätte ich gerne Verzeichnisse wie:

/models

/views

... etc


Es ist auch möglich, ein Skript von einer externen URL (anstelle einer lokalen Datei) einzuschließen. Siehe hier: pastebin.com/WkvHjGsG
Anderson Green

Das obige Skript funktioniert nur dann ordnungsgemäß, wenn Sie einen Ordner erstellen, der downloadedModulesim selben Verzeichnis wie das Skript aufgerufen wird .
Anderson Green

Antworten:


134

Mach einfach eine require('./yourfile.js');

Deklarieren Sie alle Variablen, auf die Sie von außen zugreifen möchten, als globale Variablen. Also statt

var a = "hello" es wird sein

GLOBAL.a="hello" oder nur

a = "hello"

Das ist offensichtlich schlecht. Sie möchten den globalen Bereich nicht verschmutzen. Stattdessen bezieht sich die vorgeschlagene Methode auf exportIhre Funktionen / Variablen.

Wenn Sie das MVC-Muster möchten, schauen Sie sich Geddy an.


3
Als Randnotiz .. ich liebe Express. Sie sollten es auch ausprobieren, vorausgesetzt, Sie sind nicht so speziell in Bezug auf MVC.
Shripad Krishna

42
Wenn Sie sagen "das ist offensichtlich schlecht", worauf bezieht sich "das"?
Anderson Green

1
@AndersonGreen - Er bedeutet, Variablen in einen globalen Bereich zu setzen.
Tim

77
@ AndersonGreen: Bitte sag mir, dass das ein extrem kluger Witz über Scoping war ;-)
Dusty J

6
Es hat mir geholfen zu lernen, dass es requirein Ihren npm-Modulen aussieht, wenn Sie Ihrem Pfad nicht so etwas wie./
Dylan Valade

93

Sie müssen CommonJS verstehen, ein Muster zum Definieren von Modulen. Sie sollten den GLOBAL-Bereich nicht missbrauchen, was immer schlecht ist. Stattdessen können Sie das Exporttoken wie folgt verwenden:

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

Und der Client-Code, der unser Modul verwendet:

// client.js

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

Dieser Code wurde aus der Dokumentations-API von node.js extrahiert:

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

Wenn Sie etwas wie Rails oder Sinatra verwenden möchten, empfehle ich Express (ich konnte die URL nicht posten, schade um Stack Overflow!)


64

Wenn Sie Code für Node schreiben, ist die Verwendung von Node-Modulen, wie von Ivan beschrieben, ohne Zweifel der richtige Weg.

Wenn Sie jedoch JavaScript laden müssen, das bereits geschrieben wurde und den Knoten nicht kennt, ist das vmModul der richtige Weg (und definitiv vorzuziehen eval).

Hier ist zum Beispiel mein execfileModul, das das Skript pathentweder im contextoder im globalen Kontext auswertet :

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

Beachten Sie auch: Mit geladene Module require(…)haben keinen Zugriff auf den globalen Kontext.


1
Vielen Dank für diesen Tipp. Der eigentliche Anwendungsfall ist, wenn Sie Module adhoc laden müssen. Sagen wir wie ein Registrierungsmuster, bei dem Sie 1000 Module haben würden, die sich in einem zentralen Dienst registrieren. Es ist viel sauberer und besser, nach Modulen zu suchen und sie einzeln zu laden, anstatt 1000 Anweisungen in Ihrem Dienst zu erfordern ...
Assaf Moldavsky

Da Node dynamische Anforderungen unterstützt, gibt es keinen Grund, dieses Muster beim dynamischen Laden von Node-fähigen Modulen zu verwenden. Tatsächlich ist die Verwendung dort aktiv schädlich, da sie die Knoten umgeht require.cache, sodass eine einzelne Datei möglicherweise mehrmals geladen wird.
David Wolever

Ok, um den Fall zu lösen, den ich vorgestellt habe, wo Sie 1000 Module haben, in denen sich jedes bei einem Registrierungsdienst registriert, wie verwenden Sie das, was Sie vorgeschlagen haben, ohne 1000 Anforderungsanweisungen im Registrierungsdienst zu haben?
Assaf Moldavsky

1
Wie requiregewohnt: function loadService(name) { return require('./services/' + name); }Dann listen Sie die Dienste auf, die jedoch für die Anwendung sinnvoll sind.
David Wolever

Richtig, aber das bedeutet, dass Sie alle 1000 Module im Registrierungsdienst kennen müssen. Was nicht besser ist als 1000 erfordern Anweisungen. Die ganze Idee ist, dass der Registrierungsdienst nicht alle Module kennt und sich tatsächlich um sie kümmert. Module registrieren sich ad hoc im Registrierungsdienst. Ist das sinnvoll?
Assaf Moldavsky

7

Wenn Sie die Funktionen oder Objekte einer externen Javascript-Datei laden möchten, laden Sie diesen Kontext mit dem folgenden Code - beachten Sie die runInThisContext-Methode:

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
Nach langem Suchen und Frobbing hat diese Technik bei mir funktioniert. Meine Dateien sind so geschrieben, dass der Browser sie direkt verwenden und eine Variable deklarieren kann, z. B.: Const aVar = {thing: 'a'}
lucsan

3

Wenn Sie die Antwort von @Shripad und @Ivan erweitern , würde ich empfehlen, die Standardfunktion von module.export von Node.js zu verwenden .

In Ihre Datei für Konstanten ( z. B. constants.js ) würden Sie Konstanten wie folgt schreiben:

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

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

Dann in der Datei , in der Sie wollen verwenden diese Konstanten, schreiben Sie den folgenden Code:

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

Wenn Sie die const { ... }Syntax noch nie gesehen haben: Das ist eine destrukturierende Aufgabe .


0

Entschuldigung für die Auferstehung. Sie können das Modul child_process verwenden, um externe js-Dateien in node.js auszuführen

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}`);
    }
});
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.