Как решить циклическую зависимость javascript?

Файл 1:

import b from "b.js"

class A {
    constructor(b) {
        this.b = b;
    }
}

const a = new A(b)
export default a

Файл 2:

import a from "a.js"

class B {
    constructor(a) {
        this.a = a;
    }
}

const b = new B(a)
export default b

Как такое решить? Методы класса A нужны методам класса B и наоборот.


Ответы (2 шт):

Автор решения: UserTest013

Судя по комментариях вам нужно использовать два базовых паттерна: фабрику и обозреватель. Описывать паттерны не вижу смысла, их легко можно найти в инете.

В примере ниже, класс А выполняет роль фабрики и также observable. В нем же, для упрощения, я храню массив с обьектами. Класс В является observer, а также может выступать в роли клиента/тригера для фабрики. Кнопки и event listener добавил просто для удобства, чтобы пример выглядел рабочим.

class A {

  products = [];

  observers = [];

  factory() {
    const product = new Product();
    this.products.push(product);
    document.body.insertAdjacentHTML('beforeend', `<div>
      <button class="del" data-id="${product.id}">del product ${product.id}</button>
      <button class="client" data-id="${product.id}">subscribe to ${product.id}</button>
    </div>`);
    return product;
  }

  delete(id) {
    const index = this.products.findIndex((product) => product.id === id);
    this.products.splice(index, 1);
    this.notify(id);
    document.querySelector(`[data-id="${id}"]`).parentElement.remove();
  }

  get(id) {
    return this.products.find((product) => product.id === id);
  }

  attach(observer) {
    this.observers.push(observer);
  }


  notify(id) {
    for (const observer of this.observers) {
      observer.update(id);
    }
  }

}

class B {

  subs = [];

  constructor(creator) {
    this.creator = creator;
    this.creator.attach(this);
  }

  subscribe(id) {
    const product = this.creator.get(id);
    this.subs.push({
      product
    });

  }

  update(id) {
    console.log(id);
    this.subs = this.subs.filter((sub) => sub.product.id !== id);
  }

}

class Product {
  id = String(Math.floor(Math.random() * 9999));
}

const creator = new A();

const client = new B(creator);


document.body.addEventListener('click', (event) => {
  if (event.target.classList.contains('add')) {
    const product = creator.factory();

  }
  if (event.target.classList.contains('del')) {
    creator.delete(event.target.dataset.id);
  }
  if (event.target.classList.contains('client')) {
    client.subscribe(event.target.dataset.id);
  }
  if (event.target.classList.contains('show-creator')) {
    console.log("Creator products", creator.products.map(_ => _.id).join(','));
  }
  if (event.target.classList.contains('show-client')) {
    console.log("Client subs", client.subs.map(_ => _.product.id).join(','));
  }
});
<div>
  <button class="add">add product</button>
  <button class="show-creator">display creator products</button>
  <button class="show-client">display client subs</button>
</div>

→ Ссылка
Автор решения: Lasna1

Решил так:

class A {
    constructor(b) {
        this.b = b;
        this.bInstance = null;
    }
    
    createB(B) {
      if (!this.bInstance) {
        this.bInstance = new B()
      }
      return this.bInstance;
    }
}

let a = new A()
let b = a.createB(B)
→ Ссылка