【问题标题】:Can I load multiple files with one require statement?我可以用一个 require 语句加载多个文件吗?
【发布时间】:2012-05-11 15:22:18
【问题描述】:

也许这个问题有点傻,但是是否可以使用一个 require 语句加载多个 .js 文件?像这样:

var mylib = require('./lib/mylibfiles');

并使用:

mylib.foo(); //return "hello from one"

mylib.bar(): //return "hello from two"

并且在 mylibfiles 文件夹中会有两个文件:

One.js

exports.foo= function(){return "hello from one";}

Two.js

exports.bar= function(){return "hello from two";}

我想在说要加载所有文件的文件夹中放一个 package.json,但我不知道怎么做。我正在考虑的其他方法是让 index.js 再次导出所有内容,但我将重复工作。

谢谢!!

P.D:我正在 Windows 7 机器上使用 nodejs v0.611

【问题讨论】:

    标签: node.js


    【解决方案1】:

    首先使用require 不会重复任何内容。它加载模块并缓存它,因此再次调用require 将从内存中获取它(因此您可以在不与其源代码交互的情况下即时修改模块 - 这有时是可取的,例如当你想在模块内存储数据库连接)。

    此外,package.json 不会加载任何内容,并且根本不会与您的应用程序交互。仅用于npm

    现在您不能一次需要多个模块。例如,如果One.jsTwo.js 都定义了同名的函数会发生什么?还有更多的问题。

    但是你可以做的是写额外的文件,比如modules.js,内容如下

    module.exports = {
       one : require('./one.js'),
       two : require('./two.js'),
       /* some other modules you want */
    }
    

    然后你可以简单地使用

    var modules = require('./modules.js');
    modules.one.foo();
    modules.two.bar();
    

    【讨论】:

    • 感谢您的帮助,问题是我正在尝试将一些方法作为内部方法,并且我不希望在您的示例中使用的模块可以访问这些功能,模块.js。我认为在您的示例中我也可以执行var one = require(./one.js); 并获得与one.js 相同的功能,是这样吗?
    • 更正:Node.js 实际上确实读取了package.json 文件的main 字段作为require 进程的一部分。这是 Node 从中读取的唯一内容,其余信息用于 npm
    【解决方案2】:

    我有一段需要多个模块的代码,但它并没有像您的帖子所建议的那样将它们聚集在一起。不过,这可以通过我发现的一个技巧来克服。

    function requireMany () {
        return Array.prototype.slice.call(arguments).map(function (value) {
            try {
                return require(value)
            }
            catch (event) {
                return console.log(event)
            }
        })
    }
    

    你就这样使用它

    requireMany("fs", "socket.io", "path")
    

    哪个会返回

    [ fs {}, socketio {}, path {} ]
    

    如果未找到模块,则会将错误发送到控制台。它不会破坏程序。错误将在数组中显示为未定义。数组不会因为其中一个模块加载失败而变短。

    然后您可以将这些数组元素中的每一个绑定到一个变量名,如下所示:

    var [fs, socketio, path] = requireMany("fs", "socket.io", "path")
    

    它本质上像一个对象一样工作,但将键及其值分配给全局命名空间。所以,在你的情况下,你可以这样做:

    var [foo, bar] = requireMany("./foo.js", "./bar.js")
    foo() //return "hello from one"
    bar() //return "hello from two"
    

    如果您确实希望它在出错时中断程序,只需使用这个修改后的版本,它更小

    function requireMany () {
        return Array.prototype.slice.call(arguments).map(require)
    }
    

    【讨论】:

    • 为什么默认情况下不需要 require() 就这样工作?
    【解决方案3】:

    是的,根据node docs,您可能需要一个文件夹作为模块。假设您想要 require() 一个名为 ./mypack/ 的文件夹。

    ./mypack/ 中,使用文件夹的name 创建一个package.json 文件,并在./lib/ 目录中创建一个同名的main javascript 文件。

    {
      "name" : "mypack",
      "main" : "./lib/mypack.js"
    }
    

    现在您可以使用require('./mypack'),节点将加载./mypack/lib/mypack.js

    但是,如果您不包含此 package.json 文件,它可能仍然有效。如果没有该文件,节点将尝试加载./mypack/index.js,或者如果不存在,则./mypack/index.node

    我的理解是,如果您将程序拆分为多个 javascript 文件但又不想将它们连接起来进行部署,这可能会有所帮助。

    【讨论】:

    • 只是为了清楚一点,你不能要求一个文件夹作为一个模块并让它加载该目录中的所有 javascript 文件。对吗?
    • @Michael 正确。它只会在根package.json 中加载main 的值,如果没有,则加载根index.js
    • @Michael - 动态加载代码文件的整个目录在几乎每种语言中都有相同的问题:它们应该以什么顺序加载?按字母顺序?然后你会陷入奇怪的扭曲,在文件名上添加人为前缀来影响顺序。
    • @xyz 理想情况下,顺序无关紧要 - 在我的情况下,这是真的,每个文件只是添加功能,但实际上并没有执行任何功能。
    【解决方案4】:

    您可以使用destructuring assignment 将一组从require 语句中导出的模块映射到一行中:

    const requires = (...modules) => modules.map(module => require(module));
    const [fs, path] = requires('fs', 'path');
    

    【讨论】:

      【解决方案5】:

      我正在做一些类似于@freakish 在his answer 中建议的事情,其中​​我有一个测试脚本列表,这些脚本被拉入 Puppeteer + Jest 测试设置。我的测试文件遵循命名约定 testname1.js - testnameN.js,我能够使用生成器函数通过以下方法从特定目录中获取 N 个文件:

      const fs = require('fs');
      const path = require('path');
      
      module.exports = class FilesInDirectory {
      
          constructor(directory) {
      
              this.fid = fs.readdirSync(path.resolve(directory));
              this.requiredFiles = (this.fid.map((fileId) => {
                  let resolvedPath = path.resolve(directory, fileId);
                  return require(resolvedPath);
              })).filter(file => !!file);
      
          }
      
          printRetrievedFiles() {
              console.log(this.requiredFiles);
          }
      
          nextFileGenerator() {
      
              const parent = this;
              const fidLength = parent.requiredFiles.length;
      
              function* iterate(index) {
                  while (index < fidLength) {
                      yield parent.requiredFiles[index++];
                  }
              }
              return iterate(0);
          }
      
      }
      

      然后像这样使用:

      //Use in test
      const FilesInDirectory = require('./utilities/getfilesindirectory');
      const StepsCollection = new FilesInDirectory('./test-steps');
      const StepsGenerator = StepsCollection.nextFileGenerator();
      
      //Assuming we're in an async function
      await StepsGenerator.next().value.FUNCTION_REQUIRED_FROM_FILE(someArg);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-26
        • 2014-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多