Condividi le variabili tra i file in Node.js?


126

Ecco 2 file:

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

// module.js
name = "foobar";

Quando non ho "var" funziona. Ma quando ho:

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

il nome sarà indefinito in main.js.

Ho sentito che le variabili globali sono cattive e è meglio usare "var" prima dei riferimenti. Ma è questo un caso in cui le variabili globali sono buone?

Risposte:


184

Le variabili globali non sono quasi mai una buona cosa (forse un'eccezione o due là fuori ...). In questo caso, sembra che tu voglia davvero esportare la tua variabile "name". Per esempio,

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

Quindi, 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
le variabili globali sono cattive - sono assolutamente d'accordo. Ma potrei essere, che il modulo ha una dipendenza da una variabile. C'è un modo per passare questa variabile all'altro file js tramite la funzione richiesta?
appsthatmatter il

1
@ jjoe64 Non sono sicuro di seguire ciò che intendi. È possibile condividere in modo efficace qualsiasi valore desiderato tramite l' exportsoggetto.
Jmar777,

7
L'OP chiede se una variabile può essere definita in main.js e quindi utilizzata in module.js. Ho lo stesso requisito per definire i percorsi che vengono utilizzati più e più volte.
designermonkey

4
@Designermonkey In tal caso probabilmente stai meglio avere un oggetto config con quei tipi di valori che possono anche essere richiesti () in un dato file. Nota che puoi semplicemente fare global.foo = 'bar'e quindi accedere fooovunque tu voglia ... ma come ho detto nella mia risposta originale, non è quasi mai una buona cosa.
jmar777,

Grazie per quello, ho capito come farlo, e funziona a meraviglia. Grazie per aver verificato che avevo avuto l'idea giusta :)
designermonkey

37

Non riesco a trovare uno scenario in cui un globale var sia l'opzione migliore, ovviamente puoi averne uno, ma dai un'occhiata a questi esempi e potresti trovare un modo migliore per ottenere lo stesso:

Scenario 1: inserire gli elementi nei file di configurazione

Hai bisogno di un valore che sia lo stesso in tutta l'applicazione, ma cambia a seconda dell'ambiente (produzione, sviluppo o test), il tipo di mailer come esempio, avresti bisogno di:

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

e

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

(fai una configurazione simile anche per dev)

Per decidere quale configurazione verrà caricata, creare un file di configurazione principale (che verrà utilizzato in tutta l'applicazione)

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

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

E ora puoi ottenere i dati in questo modo:

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

Scenario 2: utilizzare un file costanti

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

E usalo in questo modo

// 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);
...

Scenario 3: utilizzare una funzione di supporto per ottenere / impostare i dati

Non è un grande fan di questo, ma almeno puoi tenere traccia dell'uso del 'nome' (citando l'esempio del PO) e mettere in atto delle validazioni.

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

E usalo

// 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();
  ...

Potrebbe esserci un caso d'uso in cui non esiste altra soluzione se non quella globale var, ma di solito puoi condividere i dati nella tua app usando uno di questi scenari, se stai iniziando a usare node.js (come ero prima) per organizzare il modo in cui gestisci i dati laggiù perché possono diventare disordinati molto rapidamente.


Mi è piaciuto Scenario 2, ma questi valori possono essere modificati dopo aver parlato di build? come spesso facciamo, npm esegue build. O conosci un modo per essere in grado di modificare i valori dopo la compilazione?
Kashif Ullah,

@KashifUllah non sono sicuro di poter rispondere al tuo commento solo con le informazioni fornite, potresti voler aggiungere una nuova domanda nel sito
Felipe Pereira,

16

Se è necessario condividere più variabili, utilizzare il formato seguente

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

   module.exports={
    name,
    city,
    company
  }

uso

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

2
solo una breve nota per escludere la confusione che può sorgere al primo posto: module.exports è ciò che dovrebbe essere usato! come si chiama il tuo file js (es: global.js). Il modulo è un oggetto nodo che esiste nell'ambito globale! [quindi all'interno di global.js usiamo module.exports = .....]
Mohamed Allal

avrà successo se si rimuove il "let", e non è necessario il "module.exports .."
Ahmad Zahabi,

6

Salva qualsiasi variabile che desideri condividere come un oggetto. Quindi passalo al modulo caricato in modo che possa accedere alla variabile tramite il riferimento all'oggetto.

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

Sull'altro file ..

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

una variabile dichiarata con o senza la parola chiave var è stata collegata all'oggetto globale. Questa è la base per la creazione di variabili globali in Nodo dichiarando variabili senza la parola chiave var. Mentre le variabili dichiarate con la parola chiave var rimangono locali per un modulo.

leggi questo articolo per ulteriori informazioni - https://www.hacksparrow.com/global-variables-in-node-js.html


3
Questi frammenti contraddicono? 1) "una variabile dichiarata con o senza la parola chiave var è stata collegata all'oggetto globale". e 2) "le variabili dichiarate con la parola chiave var rimangono locali in un modulo."
BaldEagle,

1

Con un'opinione diversa, penso che le globalvariabili potrebbero essere la scelta migliore se stai per pubblicare il tuo codice npm, perché non puoi essere sicuro che tutti i pacchetti stiano usando la stessa versione del tuo codice. Quindi se usi un file per esportare asingleton oggetto, ciò causerà problemi qui.

È possibile scegliere global, require.maino altri oggetti che vengono condivisi tra i file.

Per favore, dimmi se ci sono soluzioni migliori.

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.