web-dev-qa-db-fra.com

Partage et modification d'une variable entre plusieurs fichiers node.js

main.js

var count = 1;

// psuedocode
// if (words typed begins with @add)
require('./add.js');

// if (words typed begins with @remove)
require('./remove.js');

// if (words typed begins with @total)
require('./total.js');



module.exports.count = count;

total.js

var count = require('./main.js').count;
console.log(count);

add.js

var count = require('./main.js').count;
count += 10;
console.log(count);

remove.js

var count = require('./main.js').count;
count -= 10;
console.log(count);

console.log

 1
 11
 -9

Contexte:

J'ai une application (irc bot), et je veux ajouter une fonctionnalité que peeps peut faire @add 1 ou @remove 1. J'ai un fichier main.js qui nécessite ensuite des fichiers différents en fonction des déclencheurs dits. Ainsi, add déclencherait le fichier add.js, ce qui nécessiterait alors ('main.js') et ajouter 10 (10 pour simplifier, le nombre sera alors analysé et le nombre utilisé). Le problème que je rencontre, c’est que quelqu'un se déplace et que @remove. Il nécessite ('main.js') et soustrait 10 de 1, ce qui donne -9. Et faire @total produirait 1. 

J'ai fait une assez bonne recherche pour module.exports et je n'ai pas rencontré d'exemple comme celui que j'ai cité ci-dessus. Les docs n'incluent pas d'exemples proches de ce que je veux faire; et ces questions 1 , 2 Je comprends - mais ne m’aide en rien - comme je comprends ce qui se dit là-bas.

Question:

J'aimerais que @add et @remove manipulent la même variable (count), et que @total renvoie le total de count avec @add et @removes pris en compte. Est-ce que j'utilise mal module.exports? ou existe-t-il une méthode commune de partage des variables, un fichier pouvant modifier le contenu du module.exports et renvoyant les résultats dans le fichier main.js?

31
thtsigma

Votre problème est que lorsque vous utilisez var count = require('./main.js').count;, vous obtenez une copie de ce numéro, pas une référence. Changer count ne change pas la "source".

Cependant, vous devriez avoir les fonctions d'exportation de fichiers. Exiger un fichier ne l'exécutera que la première fois, mais après cela, il sera mis en cache et ne sera pas réexécuté. voir docs

Suggestion n ° 1:

// main.js
var count = 1;
var add = require('./add.js');
count = add(count);

// add.js
module.exports = function add(count) {
    return count+10;
}

# 2:

var count = 1;
var add = function() {
    count += 10;
}
add();

# 3: Personnellement, je créerais un module compteur (c'est une instance unique, mais vous pouvez facilement en faire une "classe"):

// main.js
var counter = require('./counter.js');
counter.add();
console.log(counter.count);

// counter.js
var Counter = module.exports = {
    count: 1,
    add: function() {
        Counter.count += 10;
    },
    remove: function() {
        Counter.count += 10;
    }
}
47
MiniGod

Pas sûr que ce soit nouveau ou pas, mais vous pouvez effectivement partager des variables entre les fichiers en tant que tels:

main.js

exports.main = {
    facebook: null
};

counter.js

var jamie = require('./main'); 
console.info(jamie); //{facebook: null}
jamie.main.facebook = false;
console.info(jamie); //{facebook: false}

anothercheck.js

var jamie = require('./main'); 
console.info(jamie); //{facebook: null} //values aren't updated when importing from the same file.
jamie.main.facebook = true;
console.info(jamie); //{facebook: true}

Maintenant, vous pouvez partager entre les fichiers.

13
Jamie Hutber

J'ai le même problème que vous, .. Parfois, j'aimerais partager des variables entre plusieurs fichiers parce que j'aime le style modulaire, par exemple. en séparant le contrôleur, la fonction et les modèles dans différents dossiers/fichiers de mon script node.js afin de pouvoir gérer facilement le code.

Je ne sais pas si c'est la meilleure solution mais j'espère que cela répondra à vos besoins. 

models/data.js

// exports empty array
module.exports = [];

contrôleurs/somecontroller.js

var myVar = require('../models/data');
myVar.Push({name: 'Alex', age: 20});
console.log(myVar);
//  [{ name: 'Alex', age: 20 }]

controllers/anotherController.js

var myVar = require('../models/data');

console.log(myVar);
// This array has value set from somecontroller.js before...
//  [{ name: 'Alex', age: 20 }]

// Put new value to array
myVar.Push({name: 'John', age: 17});
console.log(myVar);
// Value will be added to an array
//  [{ name: 'Alex', age: 20 }, { name: 'John', age: 17}]
3

Il est impossible de partager une référence entre différents fichiers. Tu ne devrais pas être.

J'ai un main.js qui nécessite ensuite des fichiers différents en fonction des déclencheurs qui sont dits

Je ne pense pas que ce soit une bonne idée. Toutes les déclarations requises dont vous aurez besoin doivent figurer en haut du fichier.

Je vois aussi que vous avez besoin de main.js dans total.js et de total.js dans main.js. La fonction require() importe le module.exports du fichier et l'affecte à l'espace de noms que vous fournissez. Votre code ne devrait pas être divisé en fichiers de cette façon. Vous extrayez le code dans des fichiers séparés uniquement lorsqu'ils sont des modules par eux-mêmes. Et si vous le faites, vous n'importerez pas 2 fichiers l'un sur l'autre.

Il est également bon de noter qu'en javascript, lorsque vous attribuez quelque chose à un espace de noms, il est copié (cloné) s'il s'agit d'une primitive. S'il s'agit d'un objet, les deux espaces de noms font alors référence au même objet.

var num = 5; 
var prim = num;
prim++; // prim is 6, but num is still 5.

var num = {five:5};
var ob  = num;
ob.five = 6;
console.log(num.five) //also 6.
1
Ooo

Un petit hack qui fonctionne mais n'est pas recommandé utilise la variable process. Vous pouvez lui appliquer différentes propriétés et les utiliser essentiellement comme vous le feriez avec l’objet window dans JS basé sur un navigateur. Ce petit hack fournira une référence à la variable. Il peut être modifié et manipulé et la modification sera reportée sur tous les fichiers required.

Cependant, notez qu'il n'est pas recommandé de remplacer la variable process pourrait avoir des effets inattendus et entraînerait une perte d'informations en cas d'interférence d'un autre processus.


file1.js:

const s1 = require('./file2');
process.num = 2;
console.log("file1", process.num);
s1.changeNum();
console.log("file1", process.num);

file2.js:

module.exports.changeNum = () => {
    process.num = 3;
    console.log("file2", process.num);
};

sortie :

file1 2

file2 3

file1 3

0
Jacob Schneider