【问题标题】:Understand the behavior of require in NodeJS理解 NodeJS 中 require 的行为
【发布时间】:2020-08-16 01:38:27
【问题描述】:

我在 Node Project 中有两个 javascript 文件。 一种是路由器,里面有路由和相应的功能。 另一个是实用程序类,其中常用函数被编写为原型。说 utilservice.getSomething();

第一个文件在第二个文件中调用 utilservice.getSomething()。

我在第二个文件中导入了第一个文件(这是不必要和未使用的)。然后我在第一个文件中调用了一个 API。

我收到错误 500,说明 utilservice.getSomething() 不是函数。

我花了很多时间思考使用 Promise 出了点问题,并尝试使用 async 和 await 并陷入同样的​​错误。

最后,我删除了导入,发现 API 调用运行良好。

我的印象是 require 仅用于在另一个脚本中导入方法。但除此之外还有一些东西。网上有资源可以说明请求的目的。但我喜欢理解这种行为。

示例:

文件1.js

const utilService = require('../utils/utilService');

router.get('/something',function(req,res){
  utilService.getSomething().then((data)=>{
       //do something
 })
});

文件2.js

const file = require('../file1');

function util(){}
util.prototype.getSomething = function(){
  return "hello"
}
module.exports = new util();

我点击了 /something API。我得到了 utilservice.getSomething 不是函数。

【问题讨论】:

    标签: node.js


    【解决方案1】:

    虽然require 通常用于导入其他模块和脚本,但它也会执行这些模块中的任何代码。这允许模块覆盖其他模块的属性和对象的原型。导入模块不需要module.exports 有效。

    例如:

    文件1.js

    module.exports = {
      foo: ()=>{
        console.log("hello");
      }
    };
    

    文件2.js

    const mod = require("./File1.js");
    delete mod.foo;
    

    index.js

    const mod = require("./File1.js");
    mod.foo(); // hello
    require("./File2.js"); // undefined
    mod.foo(); // mod.foo is not a function
    

    【讨论】:

    • 考虑到您的文件 2.js,至少您对文件 1 导入做了一些事情。我什么也没做。该导入完全未使用。
    【解决方案2】:

    恭喜,您已登陆circular dependencies 的世界。我不会只告诉你那是什么,而是举个例子。

    假设您有两个文件,file1.jsfile2.js
    file1.js

    module.exports = {
      doSomething: function() {
        console.log("did something");
      }
    };
    

    file2.js:

    const util = require("./file1");
    util.doSomething();
    

    file1.js 导出了一个名为doSomething 的函数,file2.js 调用了它。所以目前,依赖树看起来像这样:

    file2.js -> requires -> file1.js
    

    现在,当您将file1.js 修改为以下内容时,就会开始出现问题:

    const file2 = require("./file2");
    module.exports = {
      doSomething: function() {
        console.log("did something");
      }
    };
    

    为什么?好了,现在我们来看看依赖树。

    file2.js -> requires -> file1.js -> requires -> file2.js -> requires -> file1.js
    

    看到问题了吗? file2.js 需要file1.js,这需要file2.js,但file2.js 需要file1.js(等等)。 Node.JS 没有陷入无限循环,而是从file1.js 加载module.exports 的当前状态(由于脚本卡在require("./file2") 上,这是未定义的),这就是您获得TypeError 的方式。

    【讨论】:

    • 哦不!我没有考虑。这是合理的。节点终端可能在服务器启动时引发错误,说明导入存在此类问题,就像在任何需要或不存在任何目录结构中存在错误的目录结构时一样。 vscode 中是否有任何库会在开始之前引发此类错误?这会很有帮助。因为,我的印象是无论如何它都没有被使用,所以它不会做任何事情。
    • 我刚刚发现了这个:npmjs.com/package/madge 这可能会有所帮助。
    • 仍在思考节点服务器最初是如何启动的。
    • 服务器启动是因为你在服务器启动时没有调用该函数。由于 JavaScript 在您尝试引用不存在的对象属性时不会抛出错误,因此程序可以正常启动。
    【解决方案3】:

    在 nodeJS 中,require 允许你从其他文件中导入模块。 它可以帮助您拆分您的应用程序并只加载必要的文件来执行它们,而不是加载一堆未使用的代码。

    它实际上以不同的名称存在于许多其他语言中:require(php)、include (php)、import (typescript、python...等)

    另一件事:为了能够正确使用 require,您必须“导出”模块、定义、函数、类...等才能在另一个脚本中使用它们,使用“module.exports”或“exports” ”。所以基本上它与“上下文”有关,或者如果你更喜欢“范围”。

    这就是为什么当您使用 package.json 执行“npm install”时会有一个名为“node_modules”的文件夹。

    多亏了“require”,您每次在应用上执行某项操作时,都可以只导入必要的内容,而不是整个项目文件。

    【讨论】:

    • 我将方法导出到文件 2 中。甚至我知道的 thag 要求也是从其他模块导入,这样我们就可以组织代码,而不是把所有东西都弄乱一个文件。为什么我想知道的是为什么内部任何地方都没有使用的不需要的导入导致代码中断。
    猜你喜欢
    • 1970-01-01
    • 2018-02-03
    • 2013-05-01
    • 1970-01-01
    • 2018-08-13
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多