web-dev-qa-db-fra.com

Node.js - vérifier si le module est installé sans en avoir réellement besoin

Je dois vérifier si "mocha" est installé avant de l'exécuter. J'ai trouvé le code suivant:

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);
}

Je n'aime pas l'idée d'attraper une exception. Y a-t-il une meilleure façon?

42
AndreyM

Vous devez utiliser require.resolve() au lieu de require(). require chargera la bibliothèque si elle est trouvée, mais require.resolve() ne le fera pas, elle renverra le nom de fichier du module.

Voir la documentation de require.resolve

try {
    console.log(require.resolve("mocha"));
} catch(e) {
    console.error("Mocha is not found");
    process.exit(e.code);
}

require.resolve () génère une erreur si le module n'est pas trouvé, vous devez donc le gérer.

66
user568109

module.paths stocke un tableau de chemins de recherche pour require. Les chemins de recherche sont relatifs au module courant d'où require est appelé. Alors:

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;
}

Et version asynchrone:

// 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);
                }
            }
        });
    });
};

Usage:

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

Ou:

isModuleAvailable("colors", function(exists)
{
    if(exists)
    {
        console.log("yay!");
    }
    else
    {
        console.log("nay:(");
    }
});

Note éditée:

  • module.paths n'est pas dans le API
  • Documentation indique que vous pouvez ajouter des chemins qui seront analysés par require mais je n'ai pas pu le faire fonctionner (je suis sous Windows XP).
1
Jan Święcki