【问题标题】:How to use module exports correctly in my local app如何在我的本地应用程序中正确使用模块导出
【发布时间】:2021-06-17 17:49:47
【问题描述】:

目前我正在从事一个个人项目,但在理解我的应用程序中 module.exports 的功能时遇到了问题...

我的应用结构如下所示:

app
├── common
│   ├── cmd
│   │   ├── run-cmd.js
├── routes
│   ├── system
│   │   ├── temp.js

我希望能够在我的应用程序的单独位置存储可重用函数(在此示例中为 run-cmd.js),并在我的应用程序的其余部分(temp.js)中轻松访问它们,而无需特别参考文件路径(例如:require(../../folder/folder/file)

这里是run-cmd.js:

const { spawn } = require("child_process");

module.exports.runCmd = (cmd, callback) => {
    var command = spawn(cmd, [], {shell:true});
    const REGEX_LINE_BREAK = /(\r\n|\n|\r)/gm;
    var result = '';

    command.stdout.on('data', function(data) {
        console.log(data.toString())
        result += data.toString().replace(REGEX_LINE_BREAK, "");
    });

    command.on('close', (code) => {
        console.log("code: " + code)
        return callback(result);
    });
} 

这里是temp.js:

var express = require('express'),
    router = express.Router(),
    runCmd = require('../../common/cmd/run-cmd');

// Add a binding to handle '/temp'
router
    .get('/temp', (req, res) => {
        runCmd('vcgencmd measure_temp', function(result) {
            console.log("Result we are prepping to send: " + result);
            res.json({result: result});
        });
    });

module.exports = router;

我觉得上面的 require() 示例破坏了使用 module.exports 的灵活性的目的......在我的应用程序中,在其他位置执行类似 require(./run-cmd) 甚至 require(from-root/path/run-cmd) 的操作会更好.此外,在这个当前示例中,我收到一条错误消息 TypeError: runCmd is not a function。

任何人都可以帮助消除我对使用 module.exports 的一些困惑并告诉我哪里出错了吗?

【问题讨论】:

  • 你看过require('path/to/runCmd')给你的东西了吗?它是一个对象,即定义的module.exports,它包含 runCmd 函数。对于绝对路径,您是否阅读过例如stackoverflow.com/q/21229944/3001761?
  • @jonrsharpe,感谢您的回复。在上面我当前的示例中,我使用的是require('path/to/runCmd'),如前所述,我得到的是TypeError: runCmd is not a function。
  • 正确;同样,它不是一个函数,它是一个对象。注销,看看。

标签: javascript node.js module.exports


【解决方案1】:

有几种方法可以实现您的愿望。一种简单但有效的解决方案是向全局对象添加一个属性。这必须在您的主(入口)js 文件中,在任何require 语句之前完成:

(以下路径是假设您的入口js文件位于app文件夹中)

global.__runCmdPath = __dirname + '/common/cmd/run-cmd';

然后,在任何其他模块中,您需要 runCmd,您可以简单地:

const runCmd = require(__runCmdPath);

您甚至可以将包含您要导出的函数的脚本的基本目录设置为全局对象的属性,然后只需附加单个脚本名称,例如:

const runCmd = require(__scriptsDir + '/run-cmd');
const runCmd2 = require(__scriptsDir + '/run-cmd2');

另一种策略是将脚本文件夹添加到 NODE_PATH 环境变量中,对于 UNIX 使用以下命令:

export NODE_PATH=./common/cmd

对于 Windows:

set NODE_PATH=./common/cmd

然后,您可以命令node app.js,这样,您就可以在任何地方简单地使用require('run-cmd')。只要您记得每次启动新的 shell 会话时都重新设置变量,这将起作用。

关于TypeError: runCmd is not a function.,如果您尝试从您需要的地方直接调用runCmd,这将继续发生。这是因为require() 返回了一个导出对象,而您导出的方法都属于这个对象。

如果你想调用你导出的 runCmd 方法,在这种情况下,你必须这样做:

runCmd.runCmd('vcgencmd measure_temp', function(result) {
            console.log("Result we are prepping to send: " + result);
            res.json({result: result});
        });

因此,您可能希望将包含导出对象的常量或 runCmd 函数的导出名称重命名为最适合您的名称。

【讨论】:

  • 这是一个很好的答案,我非常感谢您的回复。我唯一的问题是关于你对我的路径问题的解决方案。这样做有什么缺点吗?您引用了"several ways"... 这似乎是实现我想要做的最实践或推荐的方法吗?
  • 非常感谢您的反馈!以上确实是我推荐的策略,也是最常用的策略之一。唯一的缺点是 全局对象 已经有了一些应该更改的属性,因此并非所有名称都可用。你可以咨询那些here。我已经修改了我的答案以包含另一种策略,这可能会帮助您实现甚至更清洁的导入,但作为一个缺点,您需要在每次启动新的 shell 会话时设置一个环境变量。
  • 我的意思是“不应该改变的属性”
  • 这是一个很好的解释,我认为这是一个可行的解决方案。我最终选择了全球路线,因为我觉得它最适合我的情况。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-23
  • 2021-01-14
  • 2021-08-29
  • 1970-01-01
相关资源
最近更新 更多