Chame uma função "local" em module.exports de outra função em module.exports?


327

Como você chama uma função de outra função em uma module.exportsdeclaração?

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

}

Estou tentando acessar a função foode dentro da função bare estou obtendo:

TypeError: o objeto # não possui o método 'foo'

Se eu mudar this.foo()para apenas foo()eu recebo:

ReferenceError: foo não está definido


4
Testei seu código e não tenho erros. A função bar retorna indefinida porque não possui declaração de retorno. Tem certeza de que está testando corretamente?
Ferchi

1
Testado na versão do nó v8.12.0e não gera mais o erro. barnão tem nenhuma instrução de retorno portanto executar console.log(bla.bar())simplesmente retornaundefined
VladNeacsu

Respostas:


351

Mude this.foo()paramodule.exports.foo()


1
@NamNguyen Ligar exports.foo()parece um pouco estranho e difícil de ler.
Afshin Mehrabani

4
Eu acho que isso é melhor do que a resposta aceita. Se você definir funções fora do escopo das exportações, ele adicionará um nível extra de indireção e, embora às vezes seja desejável, torna mais complicado refatorar, por exemplo, renomear a função, encontrar o uso da função etc.
Pierre Henry

1
uma resposta direta à pergunta
Kermit_ice_tea

8
module.exports.foo()e exports.foo()não funciona para mim com o Node.js v5.8.0.
betweenbrain

14
imports.foo () não está funcionando, mas module.exports.foo () está funcionando com o NodeJS v6.9.1
R. Canser Yanbakan

191

Você pode declarar suas funções fora do module.exportsbloco.

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

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

Então:

module.exports = {
  foo: foo,
  bar: bar
}

11
e se eu quisesse acessar propriedades do objeto a partir do método?
Rockstar5645

1
Estou recebendo TypeError: yourClass.youMethod não é uma função quando eu fiz isso. Estou usando a versão 6.9.1 do nó. Você precisa ter uma declaração de devolução? Eu não tenho instruções de retorno, pois todo o meu código é assíncrono nas funções.
Brett Mathe

1
Comparação agradável de diferentes estilos - gist.github.com/kimmobrunfeldt/10848413
Tadas V.

Implementação muito boa! 1
realnsleo 14/09/18

3
Ou, de forma mais concisa, usando o ES6,module.exports = { foo, bar, }
Deixe-me mexer nisso

118

Você também pode fazer isso para torná-lo mais conciso e legível. Isto é o que eu vi feito em vários dos módulos de código aberto bem escritos:

var self = module.exports = {

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

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

}

Esta versão do Node.js. é específica? Estou tentando isso com a v5.8.0 e o log está indefinido.
betweenbrain

1
@doublejosh Você ... leu a pergunta? Está perguntando como você chama uma função exportada de outra. Não tem nada a ver com restrições de acesso.
Fund Monica's Lawsuit

1
Sim, eu li, por favor, releia. Esta resposta faz com que foo () seja exportado com o módulo, o que contraria o ponto de uma função "local" chamada somente dentro do módulo.
Doublejosh 18/05/19

66

Você também pode salvar uma referência ao escopo global do módulo fora da definição (module.) Imports.somemodule:

var _this = this;

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

exports.someotherfunction = function() {
   _this.somefunction();
}

É uma solução mais limpa!
IvanZh

não há necessidade dos _isso e você pode simplesmente usar este onde você precisa
Yuki

usado thisdiretamente, sem necessidade de declarar_this
Darius

1
Essa sugestão é útil uma vez que thisnão é mais a correta this. (Promessas e retornos de chamada)
Andrew McOlash

Eu gosto dessa solução da melhor maneira, pois também fornece um exemplo de escopo nos módulos do NodeJS.
miguelmorin 03/04

40

Outra opção, e mais próxima do estilo original do OP, é colocar o objeto que você deseja exportar em uma variável e fazer referência a essa variável para fazer chamadas para outros métodos no objeto. Você pode exportar essa variável e pronto.

var self = {
  foo: function (req, res, next) {
    return ('foo');
  },
  bar: function (req, res, next) {
    return self.foo();
  }
};
module.exports = self;

25
const Service = {
  foo: (a, b) => a + b,
  bar: (a, b) => Service.foo(a, b) * b
}

module.exports = Service

3
Isso é particularmente útil porque seu código está chamando Service.foo()e seu código de cliente também estará chamando Service.foo()com a mesma nomeação.
Vince Bowdren

Esta é uma resposta perfeita!
Jayant Varshney

16

A partir da versão 13 do Node.js., você pode aproveitar os Módulos ES6 .

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

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

Seguindo a abordagem de classe:

class MyClass {

    foo() {
        return 'foo';
    }

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

module.exports = new MyClass();

Isso instanciará a classe apenas uma vez, devido ao cache do módulo do Node:
https://nodejs.org/api/modules.html#modules_caching


e como se chama um método estático com essa abordagem?
Plixxer 07/07/19

@ CodeodeGod Basta chamá-lo como você chamaria qualquer outro método estático. Neste caso, se fooera estático que você chamaria isso de dentro barcomo esta: MyClass.foo().
precisa saber é o seguinte

Sim, entendi, mas como você chamaria isso de um controlador que está importando como ... const oAccounts = require ("...");
Plixxer

Você pode exportar a classe real, não uma instância da classe. Dessa forma, você pode usar seus métodos estáticos. Se você precisar usar seus métodos de instância, precisará instanciar a classe em seu controlador.
precisa saber é o seguinte

6

Para corrigir seu problema, fiz algumas alterações no bla.js e ele 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};

e nenhuma modificação no app.js

var bla = require('./bla.js');
console.log(bla.bar());

1
Na barra de função, this.foo () não funciona ... ele precisa ser foo ()
Falcoa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.