Variablen zwischen Dateien in Node.js teilen?


126

Hier sind 2 Dateien:

// main.js
require('./modules');
console.log(name); // prints "foobar"

// module.js
name = "foobar";

Wenn ich kein "var" habe, funktioniert es. Aber wenn ich habe:

// module.js
var name = "foobar";

Name wird in main.js undefiniert sein.

Ich habe gehört, dass globale Variablen schlecht sind und Sie besser "var" vor den Referenzen verwenden. Aber ist dies ein Fall, in dem globale Variablen gut sind?

Antworten:


184

Globale Variablen sind fast nie eine gute Sache (vielleicht eine oder zwei Ausnahmen da draußen ...). In diesem Fall möchten Sie anscheinend nur Ihre Variable "name" exportieren. Z.B,

// module.js
var name = "foobar";
// export it
exports.name = name;

Dann in main.js ...

//main.js
// get a reference to your required module
var myModule = require('./module');

// name is a member of myModule due to the export above
var name = myModule.name;

1
globale Variablen sind schlecht - dem stimme ich voll und ganz zu. Aber ich könnte sein, dass das Modul eine Abhängigkeit von einer Variablen hat. Gibt es eine Möglichkeit, diese Variable über die Funktion require an die andere js-Datei zu übergeben?
Appsthatmatter

1
@ jjoe64 Ich bin mir nicht sicher, was ich meine. Sie können jeden gewünschten Wert effektiv über das exportsObjekt teilen .
jmar777

7
Das OP fragt, ob eine Variable in der Datei main.js definiert und dann in module.js verwendet werden kann. Ich habe die gleiche Anforderung, Pfade zu definieren, die immer wieder verwendet werden.
Designermonkey

4
@Designermonkey In diesem Fall ist es wahrscheinlich besser, ein Konfigurationsobjekt mit den Wertetypen zu haben, die auch in einer bestimmten Datei erforderlich sein können (). Beachten Sie, dass Sie können nur das tun , global.foo = 'bar'und dann Zugang fooüberall Sie mögen ... aber wie gesagt in meiner ursprünglichen Antwort, die ist fast nie eine gute Sache.
jmar777

Vielen Dank dafür, ich habe herausgefunden, wie das geht, und es ist ein Vergnügen. Vielen Dank für die Bestätigung, dass ich die richtige Idee hatte :)
Designermonkey

37

Ich kann kein Szenario finden, in dem ein Global vardie beste Option ist. Natürlich können Sie eines haben, aber sehen Sie sich diese Beispiele an und finden Sie möglicherweise einen besseren Weg, um dasselbe zu erreichen:

Szenario 1: Legen Sie das Material in Konfigurationsdateien ab

Sie benötigen einen Wert, der für die gesamte Anwendung gleich ist, der sich jedoch je nach Umgebung (Produktion, Entwicklung oder Test) ändert, beispielsweise als Mailer-Typ, den Sie benötigen:

// File: config/environments/production.json
{
    "mailerType": "SMTP",
    "mailerConfig": {
      "service": "Gmail",
      ....
}

und

// File: config/environments/test.json
{
    "mailerType": "Stub",
    "mailerConfig": {
      "error": false
    }
}

(Machen Sie eine ähnliche Konfiguration auch für Entwickler)

Um zu entscheiden, welche Konfiguration geladen wird, erstellen Sie eine Hauptkonfigurationsdatei (diese wird in der gesamten Anwendung verwendet).

// File: config/config.js
var _ = require('underscore');

module.exports = _.extend(
    require(__dirname + '/../config/environments/' + process.env.NODE_ENV + '.json') || {});

Und jetzt können Sie die Daten wie folgt erhalten:

// File: server.js
...
var config = require('./config/config');
...
mailer.setTransport(nodemailer.createTransport(config.mailerType, config.mailerConfig));

Szenario 2: Verwenden Sie eine Konstantendatei

// File: constants.js
module.exports = {
  appName: 'My neat app',
  currentAPIVersion: 3
};

Und benutze es so

// File: config/routes.js

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

module.exports = function(app, passport, auth) {
  var apiroot = '/api/v' + constants.currentAPIVersion;
...
  app.post(apiroot + '/users', users.create);
...

Szenario 3: Verwenden Sie eine Hilfsfunktion, um die Daten abzurufen / einzustellen

Kein großer Fan von diesem, aber zumindest können Sie die Verwendung des 'Namens' (unter Berufung auf das Beispiel des OP) verfolgen und Validierungen einrichten.

// File: helpers/nameHelper.js

var _name = 'I shall not be null'

exports.getName = function() {
  return _name;
};

exports.setName = function(name) {
  //validate the name...
  _name = name;
};

Und benutze es

// File: controllers/users.js

var nameHelper = require('../helpers/nameHelper.js');

exports.create = function(req, res, next) {
  var user = new User();
  user.name = req.body.name || nameHelper.getName();
  ...

Es kann einen Anwendungsfall geben, wenn es keine andere Lösung als eine globale vargibt. Normalerweise können Sie die Daten in Ihrer App jedoch mithilfe eines dieser Szenarien freigeben, wenn Sie beginnen, node.js (wie ich es vor einiger Zeit getan habe) zu verwenden um die Art und Weise zu organisieren, wie Sie mit den Daten dort umgehen, da sie sehr schnell unordentlich werden können.


Ich mochte Szenario 2, aber können diese Werte geändert werden, nachdem wir über Build gesprochen haben? Wie so oft führen wir npm run build aus. Oder kennen Sie eine Möglichkeit, Werte nach dem Erstellen zu ändern?
Kashif Ullah

@ KashifUllah nicht sicher, ob ich Ihren Kommentar nur mit den bereitgestellten Informationen beantworten kann, möchten Sie möglicherweise eine neue Frage in die Website hinzufügen
Felipe Pereira

16

Wenn wir mehrere Variablen gemeinsam nutzen müssen, verwenden Sie das folgende Format

//module.js
   let name='foobar';
   let city='xyz';
   let company='companyName';

   module.exports={
    name,
    city,
    company
  }

Verwendung

  // main.js
    require('./modules');
    console.log(name); // print 'foobar'

2
Nur eine kurze Anmerkung, um Verwirrung zu vermeiden, die auf den ersten Blick auftreten kann: module.exports sollte verwendet werden! wie auch immer Ihre js-Datei heißt (z. B. global.js). Modul ist ein Knotenobjekt, das im globalen Bereich existiert! [Also innerhalb von global.js verwenden wir module.exports = .....]
Mohamed Allal

Es wird erfolgreich sein, wenn Sie das 'let' entfernen, und es besteht keine Notwendigkeit für das "module.exports .."
Ahmad Zahabi

6

Speichern Sie alle Variablen, die gemeinsam genutzt werden sollen, als ein Objekt. Übergeben Sie es dann an das geladene Modul, damit es über die Objektreferenz auf die Variable zugreifen kann.

// main.js
var myModule = require('./module.js');
var shares = {value:123};

// Initialize module and pass the shareable object
myModule.init(shares);

// The value was changed from init2 on the other file
console.log(shares.value); // 789

Auf der anderen Datei ..

// module.js
var shared = null;

function init2(){
    console.log(shared.value); // 123
    shared.value = 789;
}

module.exports = {
    init:function(obj){
        // Save the shared object on current module
        shared = obj;

        // Call something outside
        init2();
    }
}

1

Eine Variable, die mit oder ohne das Schlüsselwort var deklariert wurde, wurde an das globale Objekt angehängt. Dies ist die Grundlage für die Erstellung globaler Variablen in Node, indem Variablen ohne das Schlüsselwort var deklariert werden. Während Variablen, die mit dem Schlüsselwort var deklariert wurden, für ein Modul lokal bleiben.

Weitere Informationen finden Sie in diesem Artikel - https://www.hacksparrow.com/global-variables-in-node-js.html


3
Widersprechen sich diese Fragmente? 1) "Eine Variable, die mit oder ohne das Schlüsselwort var deklariert wurde, wurde an das globale Objekt angehängt." und 2) "Variablen, die mit dem Schlüsselwort var deklariert wurden, bleiben lokal für ein Modul."
BaldEagle

1

Mit einer anderen Meinung denke ich, dass die globalVariablen die beste Wahl sein könnten, wenn Sie Ihren Code npmveröffentlichen möchten, da Sie nicht sicher sein können, dass alle Pakete dieselbe Version Ihres Codes verwenden. Wenn Sie also eine Datei zum Exportieren eines singletonObjekts verwenden, treten hier Probleme auf.

Sie können oder andere Objekte auswählen global, require.maindie für mehrere Dateien freigegeben sind.

Bitte sagen Sie mir, ob es bessere Lösungen gibt.

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.