RequireJS работает по принципу, что мы можем определять функции, которые зависят от значений, возвращаемых другими функциями. Это помогает нам писать модульный код. Здесь мы будем считать, что все функции находятся в одном файле.
Запрос выглядит следующим образом:
define('moduleName',function(){
return 1;
})
require(['moduleName'],function(module1){
console.log(module1) // 1;
})
Здесь мы добавляем зависимости с помощью define
и functions
с помощью require.
Первый параметр require
— это массив зависимостей. Зависимости могут быть зарегистрированы с помощью функции define
.
Иногда мы также можем предварительно потребовать, а затем определить функции. Как только все зависимости будут разрешены, автоматически сработает определенный пользователем обратный вызов.
Сначала давайте объявим переменные на уровне модуля для хранения результатов, зависимостей и реестра функций
для сопоставления зависимостей.
const fnMap = {}; // mapping between a dependency function name to actual function reference
let registry = [] // list of functions and the names of their dependencies
const resultMap = {}; // mapping between dependency name and it's return value
Теперь, когда у нас есть переменные, давайте определим define
🙂
function define(name, cb){
fnMap[name] = cb;
const unresolvedRegistryItems = registry.filter(({ cb: userDefinedCb, dependencies }) => {
const unresolvedDeps = dependencies.filter(dependencyName => {
const fn = fnMap[dependencyName];
return !fn;
});
if (unresolvedDeps.length === 0) {
require(dependencies, userDefinedCb);
} else {
return true;
}
});
registry = unresolvedRegistryItems;
}
Как видите, мы сначала записываем зависимость в fnMap
, а затем проверяем registry
на наличие functions
, все зависимости которых разрешены. Если да, то мы вызываем require
(должно быть реализовано).
Наконец, мы обновляем список registry
отфильтрованным списком, содержащим только функции с неразрешенными зависимостями.
Давайте теперь определим require
.
function require(dependencies, cb){
const results = [];
let isResolved = true;
for (let i = 0; i < dependencies.length; i++) {
const dependencyName = dependencies[i];
const fn = fnMap[dependencyName];
if (!fn) {
isResolved = false;
registry.push({
cb,
dependencies
});
return;
}
const result = resultMap[dependencyName] || fn();
results.push(result);
resultMap[dependencyName] = result;
}
isResolved && cb.apply(null, results);
}
Готовый продукт: