Appelez une fonction «locale» dans module.exports à partir d'une autre fonction dans module.exports?

327

Comment appeler une fonction à partir d'une autre fonction dans une module.exportsdéclaration?

app.js
var bla = require('./bla.js');
console.log(bla.bar());
bla.js
module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    this.foo();
  }

}

J'essaie d'accéder à la fonction foodepuis la fonction baret j'obtiens:

TypeError: l'objet # n'a pas de méthode 'foo'

Si je change this.foo()juste, foo()je reçois:

ReferenceError: foo n'est pas défini

k00k
la source
4
J'ai testé votre code et je n'ai aucune erreur. La fonction bar renvoie undefined car n'a aucune instruction return. Êtes-vous sûr de tester correctement?
Ferchi
1
Testé en version noeud v8.12.0et ne renvoie plus l'erreur. barn'a pas de déclaration de retour, donc l'exécution console.log(bla.bar())revient simplementundefined
VladNeacsu

Réponses:

351

Remplacer this.foo()parmodule.exports.foo()

k00k
la source
1
@NamNguyen L'appel exports.foo()semble un peu gênant et difficile à lire.
Afshin Mehrabani
4
Je pense que c'est mieux que la réponse acceptée. Si vous définissez des fonctions en dehors de la portée des exportations, cela ajoute un niveau supplémentaire d'indirection, et même si cela peut être souhaitable parfois, cela rend la tâche plus compliquée, à refactoriser, par exemple renommer la fonction, trouver l'utilisation de la fonction, etc.
Pierre Henry
1
une réponse directe à la question
Kermit_ice_tea
8
module.exports.foo()et exports.foo()ne fonctionne pas pour moi avec Node.js v5.8.0.
betweenbrain
14
exports.foo () ne fonctionne pas mais module.exports.foo () fonctionne avec NodeJS v6.9.1
R. Canser Yanbakan
191

Vous pouvez déclarer vos fonctions en dehors du module.exportsbloc.

var foo = function (req, res, next) {
  return ('foo');
}

var bar = function (req, res, next) {
  return foo();
}

Ensuite:

module.exports = {
  foo: foo,
  bar: bar
}
Brett
la source
11
Et si je voulais accéder aux propriétés de l'objet à partir de la méthode?
Rockstar5645
1
Je reçois TypeError: yourClass.youMethod n'est pas une fonction lorsque j'ai fait cela. J'utilise la version 6.9.1 du nœud. Devez-vous avoir une déclaration de retour? Je n'ai pas d'instructions de retour car tout mon code est asynchrone dans les fonctions.
Brett Mathe
1
Belle comparaison de différents styles - gist.github.com/kimmobrunfeldt/10848413
Tadas V.
Très belle mise en œuvre! +1
realnsleo
3
Ou, de manière plus concise en utilisant ES6,module.exports = { foo, bar, }
Laissez-moi y
118

Vous pouvez également le faire pour le rendre plus concis et lisible. C'est ce que j'ai vu faire dans plusieurs des modules open source bien écrits:

var self = module.exports = {

  foo: function (req, res, next) {
    return ('foo');
  },

  bar: function(req, res, next) {
    self.foo();
  }

}
Calvin Alvin
la source
Cette version de Node.js est-elle spécifique? J'essaye ceci avec v5.8.0 et il se connecte indéfini.
betweenbrain
1
@doublejosh Avez-vous ... avez-vous lu la question? Il s'agit de savoir comment appeler une fonction exportée d'une autre. Cela n'a rien à voir avec les restrictions d'accès.
Action en justice de Fund Monica
1
Oui, je l'ai lu, veuillez le relire. Cette réponse rend foo () exporté avec le module, ce qui va à l'encontre du point d'une fonction "locale" appelée uniquement dans le module.
doublejosh
66

Vous pouvez également enregistrer une référence à la portée globale du module en dehors de la définition (module.) Exports.somemodule:

var _this = this;

exports.somefunction = function() {
   console.log('hello');
}

exports.someotherfunction = function() {
   _this.somefunction();
}
Ville
la source
C'est une solution plus propre!
IvanZh
pas besoin du _this et vous pouvez simplement l'utiliser lorsque vous en avez besoin
Yuki
utilisé thisdirectement, pas besoin de déclarer_this
Darius
1
Cette suggestion est utile une fois thisn'est plus la bonne this. (Promesses et rappels)
Andrew McOlash
J'aime le mieux cette solution car elle donne également un exemple de cadrage dans les modules NodeJS.
miguelmorin
40

Une autre option, et plus proche du style d'origine de l'OP, consiste à placer l'objet que vous souhaitez exporter dans une variable et à référencer cette variable pour appeler d'autres méthodes dans l'objet. Vous pouvez ensuite exporter cette variable et vous êtes prêt à partir.

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;
goozbox
la source
25
const Service = {
  foo: (a, b) => a + b,
  bar: (a, b) => Service.foo(a, b) * b
}

module.exports = Service
david_adler
la source
3
Ceci est particulièrement utilisable car votre code y appelle Service.foo()et votre code client sera également appelé Service.foo()avec le même nom.
Vince Bowdren
Ceci est une réponse parfaite!
Jayant Varshney
16

À partir de la version 13 de Node.js, vous pouvez profiter des modules ES6 .

export function foo() {
    return 'foo';
}

export function bar() {
    return foo();
}

En suivant l'approche de classe:

class MyClass {

    foo() {
        return 'foo';
    }

    bar() {
        return this.foo();
    }
}

module.exports = new MyClass();

Cela instanciera la classe une seule fois, en raison de la mise en cache du module de Node:
https://nodejs.org/api/modules.html#modules_caching

m.spyratos
la source
et comment appeler une méthode statique avec cette approche?
Plixxer
@CodeofGod Il suffit de l'appeler comme vous le feriez pour toute autre méthode statique. Dans ce cas, si fooétait statique que vous appelez à l' intérieur barcomme ceci: MyClass.foo().
m.spyratos
oui, je comprends cela, mais comment l'appeleriez-vous à partir d'un contrôleur qui l'importe comme ... const oAccounts = require ("...");
Plixxer
Vous pouvez exporter la classe réelle, pas une instance de la classe. De cette façon, vous pouvez utiliser ses méthodes statiques. Si vous devez ensuite utiliser ses méthodes d'instance, vous devrez alors instancier la classe dans votre contrôleur.
m.spyratos
6

Pour résoudre votre problème, j'ai apporté quelques modifications dans bla.js et cela fonctionne,

var foo= function (req, res, next) {
  console.log('inside foo');
  return ("foo");
}

var  bar= function(req, res, next) {
  this.foo();
}
module.exports = {bar,foo};

et aucune modification dans app.js

var bla = require('./bla.js');
console.log(bla.bar());
Akash Jain
la source
1
Dans la barre de fonctions, this.foo () ne fonctionne pas ... il doit être foo ()
Falcoa