Charger et exécuter un fichier js externe dans node.js avec accès aux variables locales?


130

Est-il facile / possible de faire un include('./path/to/file')type simple de commande dans node.js?

Tout ce que je veux faire, c'est avoir accès aux variables locales et exécuter un script. Comment les gens organisent-ils généralement les projets node.js qui sont plus grands qu'un simple monde Hello? (Un site Web dynamique entièrement fonctionnel)

Par exemple, j'aimerais avoir des répertoires comme:

/models

/views

... etc


Il est également possible d'inclure un script à partir d'une URL externe (au lieu d'un fichier local). Voir ici: pastebin.com/WkvHjGsG
Anderson Green

Le script ci-dessus ne fonctionne correctement que si vous créez un dossier appelé downloadedModulesdans le même répertoire que le script.
Anderson Green

Réponses:


134

Faites juste un require('./yourfile.js');

Déclarez toutes les variables auxquelles vous souhaitez un accès extérieur en tant que variables globales. Donc au lieu de

var a = "hello" ce sera

GLOBAL.a="hello" ou juste

a = "hello"

C'est évidemment mauvais. Vous ne voulez pas polluer la portée mondiale. Au lieu de cela, la méthode suggérée est à exportvos fonctions / variables.

Si vous voulez le modèle MVC, jetez un œil à Geddy.


3
En passant, j'adore Express. Vous devriez le vérifier aussi, à condition que vous ne soyez pas si particulier sur MVC.
Shripad Krishna

43
Quand vous dites «c'est manifestement mauvais», à quoi se réfère «ceci»?
Anderson Green

1
@AndersonGreen - Il veut dire mettre des variables dans une portée globale.
Tim du

77
@AndersonGreen: S'il vous plaît dites-moi que c'était une blague extrêmement intelligente sur la portée ;-)
Dusty J

6
Cela m'a aidé à apprendre que cela requireressemble à vos modules npm si vous ne préfixez pas votre chemin avec quelque chose comme./
Dylan Valade

93

Vous devez comprendre CommonJS, qui est un modèle pour définir des modules. Vous ne devriez pas abuser de la portée GLOBALE qui est toujours une mauvaise chose à faire, à la place, vous pouvez utiliser le jeton `` exportations '', comme ceci:

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

Et le code client qui utilisera notre module:

// client.js

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

Ce code a été extrait de l'API de documentation node.js:

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

De plus, si vous voulez utiliser quelque chose comme Rails ou Sinatra, je recommande Express (je ne pouvais pas publier l'URL, dommage sur Stack Overflow!)


64

Si vous écrivez du code pour Node, utiliser les modules Node comme décrit par Ivan est sans aucun doute la voie à suivre.

Cependant, si vous devez charger du JavaScript qui a déjà été écrit et que vous ne connaissez pas le nœud, le vmmodule est la voie à suivre (et certainement préférable eval).

Par exemple, voici mon execfilemodule, qui évalue le script à l' pathun contextou l' autre ou dans le contexte global:

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

A noter également: les modules chargés avec require(…)n'ont pas accès au contexte global.


1
Merci pour cette astuce. Le vrai cas d'utilisation est celui où vous devez charger des modules adhoc. Dites comme un modèle d'enregistrement où vous auriez 1000 modules qui s'inscriraient dans un service central. Il est beaucoup plus propre et mieux conçu de rechercher des modules et de les charger un par un plutôt que de faire 1000 déclarations d'exigence dans votre service ...
Assaf Moldavsky

Node prend en charge les exigences dynamiques, il n'y a donc aucune raison d'utiliser ce modèle lors du chargement dynamique de modules compatibles avec les nœuds. En fait, il est activement dangereux de l'utiliser, car il contourne celui de Node require.cache, de sorte qu'un seul fichier peut être chargé plusieurs fois.
David Wolever

Ok, donc pour résoudre le cas que j'ai présenté où vous avez un 1000 modules où chacun s'inscrit dans un service de registre, comment utilisez-vous ce que vous avez proposé sans avoir un 1000 instructions require dans le service de registre?
Assaf Moldavsky

1
Tout requirecomme d'habitude: function loadService(name) { return require('./services/' + name); }puis listez les services mais cela a du sens pour l'application.
David Wolever

Bien, mais cela implique que vous devez connaître tous les 1000 modules du service de registre. Ce qui n'est pas mieux que d'avoir un 1000 instructions require. L'idée générale est que le service de registre ne connaît pas tous les modules et en fait il se soucie d'eux. Les modules s'enregistrent ad hoc dans le service de registre. Cela a-t-il du sens?
Assaf Moldavsky

7

Si vous prévoyez de charger les fonctions ou les objets d'un fichier javascript externe, chargez-le sur ce contexte à l'aide du code suivant - notez la méthode 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
Après beaucoup de recherches et de frobbing, cette technique a fonctionné pour moi. Mes fichiers sont écrits pour que le navigateur les utilise directement et déclare une variable par exemple: const aVar = {thing: 'a'}
lucsan

3

En développant la réponse de @Shripad et @Ivan , je vous recommande d'utiliser la fonctionnalité module.export standard de Node.js.

Dans votre fichier pour les constantes ( par exemple constants.js ), vous écririez des constantes comme ceci:

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

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

Ensuite, dans le fichier dans lequel vous souhaitez utiliser ces constantes, écrivez le code suivant:

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

Si vous n'avez jamais vu la const { ... }syntaxe auparavant: c'est une affectation destructrice .


0

Désolé pour la résurrection. Vous pouvez utiliser le module child_process pour exécuter des fichiers js externes dans 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}`);
    }
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.