¿Llamar a una función "local" dentro de module.exports desde otra función en module.exports?

327

¿Cómo se llama a una función desde otra función en una module.exportsdeclaración?

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();
  }

}

Estoy tratando de acceder a la función foodesde dentro de la función bary obtengo:

TypeError: Object # no tiene el método 'foo'

Si cambio this.foo()a solo foo()obtengo:

ReferenceError: foo no está definido

k00k
fuente
44
Probé tu código y no tengo errores. La función de barra devuelve indefinido porque no tiene declaración de devolución. ¿Estás seguro de que estás probando correctamente?
Ferchi
1
Probado en la versión de nodo v8.12.0y ya no arroja el error. barno tiene declaración de devolución, por lo que la ejecución console.log(bla.bar())simplemente regresaundefined
VladNeacsu

Respuestas:

351

Cambiar this.foo()amodule.exports.foo()

k00k
fuente
1
@NamNguyen Calling exports.foo()parece un poco incómodo y difícil de leer.
Afshin Mehrabani
44
Creo que esto es mejor que la respuesta aceptada. Si define funciones fuera del alcance de las exportaciones, que añade un nivel adicional de direccionamiento indirecto, y si bien puede ser a veces deseables, lo hace más complicado, a perfeccionar por, por ejemplo, cambiar el nombre de la función, el uso del hallazgo de la función, etc
Pierre Henry
1
una respuesta directa a la pregunta
Kermit_ice_tea
8
module.exports.foo()y exports.foo()no funciona para mí con Node.js v5.8.0.
betweenbrain
14
exportaciones.foo () no funciona pero module.exports.foo () funciona con NodeJS v6.9.1
R. Canser Yanbakan
191

Puede declarar sus funciones fuera del module.exportsbloque.

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

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

Luego:

module.exports = {
  foo: foo,
  bar: bar
}
Brett
fuente
11
¿Qué pasa si quisiera acceder a las propiedades del objeto desde el método?
Rockstar5645
1
Recibo TypeError: yourClass.youMethod no es una función cuando hice esto. Estoy usando la versión de nodo 6.9.1. ¿Tiene que tener una declaración de devolución? No tengo declaraciones de devolución ya que todo mi código es asíncrono en las funciones.
Brett Mathe
1
Buena comparación de diferentes estilos - gist.github.com/kimmobrunfeldt/10848413
Tadas V.
Muy buena implementación! +1
realnsleo
3
O, de manera más concisa usando ES6,module.exports = { foo, bar, }
Déjenme pensarlo el
118

También puede hacer esto para hacerlo más conciso y legible. Esto es lo que he visto hacer en varios de los módulos de código abierto bien escritos:

var self = module.exports = {

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

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

}
Calvin Alvin
fuente
¿Es específica esta versión de Node.js? Estoy intentando esto con v5.8.0 y está registrando indefinido.
betweenbrain
1
@doublejosh ¿... leíste la pregunta? Se pregunta cómo llamar a una función exportada desde otra. No tiene nada que ver con restricciones de acceso.
Fondo de la demanda de Mónica
1
Sí, lo leí, vuelve a leerlo. Esta respuesta hace que foo () se exporte con el módulo, lo que va en contra del punto de una función "local" que solo se llama dentro del módulo.
doublejosh
66

También puede guardar una referencia al alcance global del módulo fuera de la definición (module.) Exports.somemodule:

var _this = this;

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

exports.someotherfunction = function() {
   _this.somefunction();
}
Ville
fuente
¡Es una solución más limpia!
IvanZh
no necesita el _esto y simplemente puede usarlo donde lo necesite
Yuki
usado thisdirectamente, no es necesario declarar_this
Darius
1
Esa sugerencia es útil una vez thisque ya no es la correcta this. (Promesas y devoluciones de llamada)
Andrew McOlash
Esta solución me gusta más porque también da un ejemplo de alcance en los módulos NodeJS.
miguelmorin
40

Otra opción, y más cercana al estilo original del OP, es colocar el objeto que desea exportar en una variable y hacer referencia a esa variable para realizar llamadas a otros métodos en el objeto. Luego puede exportar esa variable y listo.

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

module.exports = Service
david_adler
fuente
3
Esto es particularmente útil porque su código está llamando Service.foo(), y su código de cliente también llamará Service.foo()con el mismo nombre.
Vince Bowdren
Esta es una respuesta perfecta!
Jayant Varshney
16

A partir de la versión 13 de Node.js , puede aprovechar los módulos ES6 .

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

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

Siguiendo el enfoque de clase:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

Esto creará una instancia de la clase solo una vez, debido al almacenamiento en caché del módulo de Node:
https://nodejs.org/api/modules.html#modules_caching

m.spyratos
fuente
¿Y cómo se llama a un método estático con este enfoque?
Plixxer
@CodeofGod Simplemente llámelo como llamaría a cualquier otro método estático. En este caso, si fooera estática que le llama desde el interior de barla siguiente manera: MyClass.foo().
m.spyratos
sí, lo entiendo, pero ¿cómo lo llamarías desde un controlador que lo está importando como ... const oAccounts = require ("...");
Plixxer
Puede exportar la clase real, no una instancia de la clase. De esa manera puedes usar sus métodos estáticos. Sin embargo, si necesita utilizar sus métodos de instancia, deberá crear una instancia de la clase en su controlador.
m.spyratos
6

Para solucionar su problema, he realizado algunos cambios en bla.js y está funcionando,

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

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

y ninguna modificación en app.js

var bla = require('./bla.js');
console.log(bla.bar());
Akash Jain
fuente
1
En la barra de funciones, this.foo () no funciona ... necesita ser foo ()
Falcoa