Node.JS load module async

后端 未结 1 2003
执笔经年
执笔经年 2021-02-07 23:29

I would like to have the ability to load a module that has been changed. I would have to of course unload the module first. Since this is a webserver setup, I am asking if there

1条回答
  •  逝去的感伤
    2021-02-08 00:16

    I posted this answer, but you are welcome to post an improvement.

    See the Node.JS source code.

    Module.prototype.require = function(path) { return Module._load(path, this); };

    Abridged version of _load

    Module._load = function(request, parent, isMain) {
      var filename = Module._resolveFilename(request, parent);
      if (Module._cache[filename]) return Module._cache[filename].exports;
      if (NativeModule.exists(filename)) {
        if (filename == 'repl') { // special case, needs the real require.
          var replModule = new Module('repl');
          replModule._compile(NativeModule.getSource('repl'), 'repl.js');
          NativeModule._cache.repl = replModule;
          return replModule.exports;
        }
        return NativeModule.require(filename);
      }
      var module = new Module(filename, parent);
      if (isMain) process.mainModule = module, module.id = '.';
      Module._cache[filename] = module;
      var hadException = true;
      try {
        module.load(filename);
        hadException = false;
      } finally {
        if (hadException) delete Module._cache[filename];
      }
      return module.exports;
    };
    

    My version of require.async.js will be something like

    var NativeModule = require('native_module');
    var fs = require('fs');
    if(!require.async) require.async = function (path, callback) { module.exports(path, this, callback); } // Comment out if you dislike using globals
    module.exports = function(request, parent, callback) {
      var filename = Module.resolve(request, parent); // This is a Sync function. TODO, change it to an async function with a callback.
      if (Module.cache[filename]) callback(Module.cache[filename].exports);
      else if (NativeModule.exists(filename)) callback(new Error('What are you thinking?'))
      else fs.readFile(filename, 'utf8', function(err, file) {
        if (Module.cache[filename]) callback(null, Module.cache[filename].exports); // For the case when there are two calls to require.async at a time.
        else if(err) callback(err)
        else {
          var module = new Module(filename, parent);
          try {
            module._compile(file);
            Module.cache[filename] = module;
          } catch(ex) {
            callback(err)
          }
          if(Module.cache[filename]) callback(null, module.exports)
        }
    }
    

    Caveats

    • There is one TODO in the code which is to make the multiple calls to stat to be async. The actual reading of the file is regular async, so that is good.
    • If you are async loading a module, and that module you are loading is sync loading another module, then you have not fully gone async with your code - have you.
    • It uses one private method - _compile.

    0 讨论(0)
提交回复
热议问题