Saltar al contenido

Carga de módulos de Node.js dinámicamente según la ruta

Este tutorial fue evaluado por expertos así se garantiza la exactitud de nuestra esta sección.

Solución:

Si sabe dónde están sus scripts, es decir, tiene un directorio inicial, por ejemplo DIR, entonces puedes trabajar con fs, por ejemplo:

server.js

var fs = require('fs');
var path_module = require('path');
var module_holder = ;

function LoadModules(path) 
    fs.lstat(path, function(err, stat) 
        if (stat.isDirectory()) 
            // we have a directory: do a tree walk
            fs.readdir(path, function(err, files) 
                var f, l = files.length;
                for (var i = 0; i < l; i++) 
                    f = path_module.join(path, files[i]);
                    LoadModules(f);
                
            );
         else 
            // we have a file: load it
            require(path)(module_holder);
        
    );

var DIR = path_module.join(__dirname, 'lib', 'api');
LoadModules(DIR);

exports.module_holder = module_holder;
// the usual server stuff goes here

Ahora sus scripts deben seguir la siguiente estructura (debido a la require(path)(module_holder) línea), por ejemplo:

user_getDetails.js

function handler(req, res) 
    console.log('Entered my cool script!');


module.exports = function(module_holder) 
    // the key in this dictionary can be whatever you want
    // just make sure it won't override other modules
    module_holder['user_getDetails'] = handler;
;

y ahora, al manejar una solicitud, lo hace:

// request is supposed to fire user_getDetails script
module_holder['user_getDetails'](req, res);

Esto debería cargar todos sus módulos a module_holder variable. No lo probé, pero debería funcionar (excepto por el manejo de errores !!!). Es posible que desee modificar esta función (por ejemplo, hacer module_holder un árbol, no un diccionario de un nivel) pero creo que comprenderá la idea.

Esta función debería cargarse una vez por inicio del servidor (si necesita activarla con más frecuencia, entonces probablemente esté lidiando con secuencias de comandos dinámicas del lado del servidor y esta es una idea baaaaaad, en mi humilde opinión). Lo único que necesita ahora es exportar module_holder objeto para que cada controlador de vista pueda usarlo.

app.js

var c_file = 'html.js';

var controller = require(c_file);
var method = 'index';

if(typeof controller[method] === 'function')
    controller[method]();

html.js

module.exports =

    index: function()
    
        console.log('index method');
    ,
    close: function()
    
        console.log('close method');    
    
;

dinamizando este código un poco puedes hacer cosas mágicas: D

A continuación, se muestra un ejemplo de un servicio web de API REST que carga dinámicamente el archivo js del controlador en función de la URL enviada al servidor:

server.js

var http = require("http");
var url = require("url");

function start(port, route) 
   function onRequest(request, response) 
       var pathname = url.parse(request.url).pathname;
       console.log("Server:OnRequest() Request for " + pathname + " received.");
       route(pathname, request, response);
   

   http.createServer(onRequest).listen(port);
   console.log("Server:Start() Server has started.");


exports.start = start;

router.js

function route(pathname, req, res) 
    console.log("router:route() About to route a request for " + pathname);

    try 
        //dynamically load the js file base on the url path
        var handler = require("." + pathname);

        console.log("router:route() selected handler: " + handler);

        //make sure we got a correct instantiation of the module
        if (typeof handler["post"] === 'function') 
            //route to the right method in the module based on the HTTP action
            if(req.method.toLowerCase() == 'get') 
                handler["get"](req, res);
             else if (req.method.toLowerCase() == 'post') 
                handler["post"](req, res);
             else if (req.method.toLowerCase() == 'put') 
                handler["put"](req, res);
             else if (req.method.toLowerCase() == 'delete') 
                handler["delete"](req, res);
            

            console.log("router:route() routed successfully");
            return;
         
     catch(err) 
        console.log("router:route() exception instantiating handler: " + err);
    

    console.log("router:route() No request handler found for " + pathname);
    res.writeHead(404, "Content-Type": "text/plain");
    res.write("404 Not found");
    res.end();



exports.route = route;

index.js

var server = require("./server");
var router = require("./router");

server.start(8080, router.route);

los controladores en mi caso están en una subcarpeta / TrainerCentral, por lo que el mapeo funciona así:

localhost: 8080 / TrainerCentral / Recipe se asignará al archivo js /TrainerCentral/Recipe.js localhost: 8080 / TrainerCentral / Workout se asignará al archivo js /TrainerCentral/Workout.js

aquí hay un controlador de ejemplo que puede manejar cada una de las 4 acciones HTTP principales para recuperar, insertar, actualizar y eliminar datos.

/TrainerCentral/Workout.js

function respond(res, code, text) 
    res.writeHead(code,  "Content-Type": "text/plain" );
    res.write(text);
    res.end();


module.exports = 
   get: function(req, res) 
       console.log("Workout:get() starting");

       respond(res, 200, " 'id': '123945', 'name': 'Upright Rows', 'weight':'125lbs' ");
   ,
   post: function(request, res) 
       console.log("Workout:post() starting");

       respond(res, 200, "inserted ok");
   ,
   put: function(request, res) 
       console.log("Workout:put() starting");

       respond(res, 200, "updated ok");
   ,
   delete: function(request, res) 
       console.log("Workout:delete() starting");

       respond(res, 200, "deleted ok");
   
;

inicie el servidor desde la línea de comando con "node index.js"

¡Divertirse!

Comentarios y calificaciones de la guía

Si te animas, eres capaz de dejar una reseña acerca de qué le añadirías a esta noticia.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *