Ответ 1
Я отправил этот ответ, но вы можете опубликовать улучшение.
Смотрите исходный код 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;
};
Моя версия 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)
}
}
Предостережение
- В коде есть один TODO, который должен сделать несколько вызовов
stat
для асинхронизации. Фактическое чтение файла является регулярным асинхронным, так что это хорошо. - Если вы загружаете модуль с асинхронной загрузкой, и этот модуль, который вы загружаете, синхронизируется с загрузкой другого модуля, то вы не полностью ушли с асинхронным кодом. У вас есть.
- Он использует один закрытый метод -
_compile
.