Поверьте мне, вам нужно удалить эти циклические зависимости в вашем проекте!
Мир JavaScript делает упор на модульный код, однако поддержка циклических зависимостей ограничена. Здесь я предлагаю раз и навсегда решить эту проблему — используя то, что я называю связыванием API.
Случай
При разработке библиотеки JavaScript с множественной точностью я накопил около 1000 строк кода в BigInteger файле. Это неприемлемый объем кода в одном файле, поэтому я решил разобрать его на части.
husky-multiprecision/
src/
BigInteger.js
IntegerMultiplication.js // provides a static multiply()
IntegerDivision.js // provides a static divide()
index.js
В состав моего проекта входили эти файлы. IntegerDivision и IntegerMultiplication, очевидно, зависят от BigInteger, а BigInteger зависят от двух других для предоставления функций API BigInteger.multiply() и BigInteger.divide(). Теперь использование циклических зависимостей здесь не является решением — это потому, что это библиотека, а не приложение, которое должно удовлетворять всем типам модульных систем, включая те, которые не любят циклические зависимости.
Привязка API расширения к классу BigInteger позволит внешним модулям использовать BigInteger.multiply() и BigInteger.divide(), а внутренние файлы будут использовать API IntegerMultiplication и IntegerDivision.
Давайте использовать привязку
Поскольку внешним библиотекам и приложениям, использующим мою библиотеку с множественной точностью, «потребуется» файл index.js, и они не будут касаться какого-либо внутреннего файла, я могу скрыть циклическую зависимость внутри каталога src, создав «API-расширение» и привязав его к BigInteger класс.
// husky-multiprecision/BigInteger.extension.js
// After binding BigIntegerExtension_* functions to
// the BigInteger class (in index.js), we can call
// multiply and divide on a BigInteger object.
const BigInteger = require('./BigInteger');
const IntegerMultiplication = require('./IntegerMultiplication');
const IntegerDivision = require('./IntegerDivision);
function BigIntegerExtension_multiply(other) {
return IntegerMultiplication.multiply(this, other);
}
function BigIntegerExtension_divide(other) {
return IntegerDivision.divide(this, other);
}
module.exports = {
multiply: BigIntegerExtension_multiply,
divide: BigIntegerExtension_divide
);
Теперь нам нужно «привязать» API к BigInteger.extension.js:
// husky-multiprecision/index.js
/*
* Code in the global scope here is invoked only once,
* no matter how many times this file is imported, hence,
* don't worry about the binding occurring more than
* once.
*
* Don't believe me, try adding console.log("Binder"); anywhere
* here and import it twice. "Binder" will be shown only once.
*/
const BigInteger = require('./src/BigInteger');
const BigIntegerExtAPI = require('./BigInteger.extension.js');
BigInteger.prototype.multiply = BigIntegerExtAPI.multiply;
BigInteger.prototype.divide = BigIntegerExtAPI.divide;
module.exports = {
BigInteger: BigInteger
};
Ура!!! Теперь вы можете использовать шаблон привязки для создания изящного модульного кода без циклических зависимостей.