Node.js-检查模块是否已安装,而实际上并不需要它

Node.js-检查模块是否已安装,而实际上并不需要它,node.js,module,require,Node.js,Module,Require,在运行之前,我需要检查是否安装了“摩卡”。我想出了以下代码: try { var mocha = require("mocha"); } catch(e) { console.error(e.message); console.error("Mocha is probably not found. Try running `npm install mocha`."); process.exit(e.code); } 我不喜欢抓住一个例外的想法。有更好的方法吗?您

在运行之前,我需要检查是否安装了“摩卡”。我想出了以下代码:

try {
    var mocha = require("mocha");
} catch(e) {
    console.error(e.message);
    console.error("Mocha is probably not found. Try running `npm install mocha`.");
    process.exit(e.code);
}

我不喜欢抓住一个例外的想法。有更好的方法吗?

您应该使用
require.resolve()
而不是
require()
require
将加载找到的库,但
require.resolve()
不会,它将返回模块的文件名


如果找不到模块,require.resolve()会抛出错误,因此您必须处理它。

module.path
存储
require
的搜索路径数组。搜索路径相对于调用
require
的当前模块。因此:

var fs = require("fs");

// checks if module is available to load
var isModuleAvailableSync = function(moduleName)
{
    var ret = false; // return value, boolean
    var dirSeparator = require("path").sep

    // scan each module.paths. If there exists
    // node_modules/moduleName then
    // return true. Otherwise return false.
    module.paths.forEach(function(nodeModulesPath)
    {
        if(fs.existsSync(nodeModulesPath + dirSeparator + moduleName) === true)
        {
            ret = true;
            return false; // break forEach
        }
    });

    return ret;
}
和异步版本:

// asynchronous version, calls callback(true) on success
// or callback(false) on failure.
var isModuleAvailable = function(moduleName, callback)
{
    var counter = 0;
    var dirSeparator = require("path").sep

    module.paths.forEach(function(nodeModulesPath)
    {
        var path = nodeModulesPath + dirSeparator + moduleName;
        fs.exists(path, function(exists)
        {
            if(exists)
            {
                callback(true);
            }
            else
            {
                counter++;

                if(counter === module.paths.length)
                {
                    callback(false);
                }
            }
        });
    });
};
用法:

if( isModuleAvailableSync("mocha") === true )
{
    console.log("yay!");
}
或:

编辑:注:

  • 模块路径
    不在
  • 您可以添加将由
    扫描的路径的文档需要
    ,但我无法使其工作(我使用的是Windows XP)

require.resolve
仍然会抛出一个错误—这是我试图避免的—捕获异常。接受答案,因为其他解决方案在任何方面都不干净。是的,但这也会查找全局安装的模块吗?我想检查模块是否安装在本地。@更好的方法是使用where global默认为false。我已经回答了,但现在我注意到了“global”这个词。“全局”是指在
npm
中安装了
-g
选项的模块吗?例如,npm安装-g摩卡?编辑:AFAIK
require
将找不到安装了
-g
选项的模块。@AndreyM,只是想知道您不喜欢这个解决方案的哪些地方,以及为什么您将接受的答案标记为使用try/catch hack来确定模块是否存在的答案?谢谢。我假设module.paths不在API中,您没有使用它。我可以看出,如果节点以某种方式发生更改,这将不会成为未来的证明,而try/catch策略尽管很难看,但会更可靠。尽管如此,这是一个非常棒的答案,不需要尝试/抓住就可以解决这个问题+1 :)
if( isModuleAvailableSync("mocha") === true )
{
    console.log("yay!");
}
isModuleAvailable("colors", function(exists)
{
    if(exists)
    {
        console.log("yay!");
    }
    else
    {
        console.log("nay:(");
    }
});