在模块内部调用一个Node.js模块函数

5
我将尝试编写一个Node模块,以便清理我的代码并将其分离成不同的文件。
请考虑下面的代码:
module.exports = {
    Hello : function(request, reply) {
        return reply("Hello " + World());
    },
    World : function() {
        return "World";
    }
}

如果我引入上述模块并将Hello函数作为特定路由的处理程序使用,我会收到HTTP 500内部服务器错误。

我已经将问题缩小到对World()函数的调用,如果我将Hello函数更改为

Hello : function(request, reply) {
    return reply("Hello World");
}

然后它可以正常工作,因此似乎在从导出对象内部调用另一个函数时被绊倒了。

有人知道这是为什么以及如何解决吗?


https://jsfiddle.net/rc62tuw8/ - Andy
奇怪。它在Fiddle中可以工作,但是在我的应用程序中似乎不受欢迎。 - Michael
你在哪里准确地调用了myModule.Hello函数呢? - Redu
@Michael,我建议你尝试使用我的答案中提到的server.route({ method: 'GET', path: '/user/new/{q}', handler: testy.Hello.bind(testy)});。当然,在testy中,你应该有return reply("Hello " + this.World()) - Redu
谢谢,是的,我认为那也可以行得通,但我认为在exports对象之外声明函数看起来更清晰。非常令人困惑,但它正在工作。 - Michael
显示剩余3条评论
3个回答

5
您应该按照以下方式进行调用:
module.exports = {
    Hello: function(request, reply) {
        return reply("Hello " + module.exports.World());
    },
    World: function() {
        return "World";
    }
}

如果您想要更干净的代码,我建议您将代码更改为以下内容:
function World() {
  return "World";
}
function Hello(request, reply) {
  return reply("Hello " + World());
}
module.exports = {
    Hello,
}

这将使您的代码更易读,并且您只会导出实际需要的内容。这个问题有其他解决方案可供参考。


你的第二个例子很好!非常奇怪,第一个例子不行。 - Michael

3

好的,让我们来演示一下this

this并不定义函数所在的对象,它定义了函数被调用的位置。因此,当;

var obj = {
    Hello : function(request, reply) {
        return reply("Hello " + this.World());
    },
    World : function() {
        return "World";
    }
};
obj.Hello("test", console.log);

这个是可以正常工作的;但这个则不行;

var obj = { Hello : function(request, reply) {
                      return reply("Hello " + this.World());
                    },
            World : function() {
                      return "World";
                    }
          };

setTimeout(obj.Hello,100,"test",console.log);

这是因为setTimeOut函数的定义中将给obj.Hello分配一个参数,并且该参数将作为window被调用,成为该函数的this。因此,你应该像这样做:

var obj = { Hello : function(request, reply) {
                      return reply("Hello " + this.World());
                    },
            World : function() {
                      return "World";
                    }
          };

setTimeout(obj.Hello.bind(obj),100,"test",console.log);
//or 
setTimeout(obj.Hello.bind(obj,"test",console.log),100);
//or
setTimeout((x,y) => obj.Hello(x,y),100,"test",console.log);


这是非常有帮助的解释,我原以为reply()函数可能在幕后做了一些“魔法”,导致它出了问题,但是Ahmad的答案(第二部分)很好地解决了这个问题,而且基本上完全相同,只是语法不同。我真的很困惑原因是什么,但无论如何它现在可以工作了。 - Michael
@Michael,请查看您问题下面的评论。只要您在testy模块的Hello方法中有return reply("Hello " + this.World());指令,它应该可以正常工作,无论reply执行了什么魔法。 - Redu

2
您需要在调用World()时添加this -
module.exports = {
    Hello : function(request, reply) {
        return reply("Hello " + this.World());
    },
    World : function() {
        return "World";
    }
}

World是导出对象的一个属性,而不是可访问范围内的变量 - 因此您需要指定该函数属于this


我也是这么想的,但是没有效果 - 我仍然得到了 HTTP 500。 - Michael
出于好奇,reply 定义在哪里? - skwidbreth
只有在模块中执行 Hello 函数,例如 someModule.Hello(),才能正常工作。但是当导出回调函数用于 Web 服务器时,这种情况不太可能发生。 - Brandon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接