Node.JS加载模块异步

Bry*_*eld 12 asynchronous module require node.js

我希望能够加载已更改的模块.我当然要先卸载模块.由于这是一个Web服务器设置,我问是否有办法以异步方式加载模块,以避免在读取更新文件期间冻结Web服务器.

一段时间后Node.JS删除了该require.async功能.那么,在最新版本的Node.JS上,推荐的替代方案是什么?

  • 我应该先读取整个文件,然后使用该Module库来解析文件内容.(与在内部读取和解析文件名的默认功能相反)如何?
  • 我应该将这份工作外包给一些开源图书馆吗?哪一个?
  • 我应该编写自己的模块处理程序 - 我自己的实现requireAsync吗?(我知道该怎样.)

注意:除了加载模块异步之外,我不想做任何其他事情,因此请不要建议我用新的Web服务器路由框架替换我的设置.

Bry*_*eld 5

我发布了这个答案,但欢迎你发表改进.

请参阅Node.JS源代码.

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

简明版 _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;
};
Run Code Online (Sandbox Code Playgroud)

我的版本require.async.js会是这样的

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

注意事项

  • 代码中有一个TODO,用于使多个调用stat异步.文件的实际读取是常规的异步,所以这很好.
  • 如果您正在异步加载模块,并且您正在加载的模块是同步加载另一个模块,那么您还没有完全与代码异步 - 请你.
  • 它使用一种私有方法 - _compile.