この解答例はChatGPTによって生成されています,正しいかは自己判断で。

BFE.devでのAI解答例 - JavaScript コーディング問題
71. Observable Subjectを実装する

class Subject {
  constructor() {
    this.observers = [];
  }

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

  unsubscribe(observer) {
    this.observers = this.observers.filter((obs) => obs !== observer);
  }

  next(value) {
    for (let observer of this.observers) {
      if (observer.next) {
        observer.next(value);
      } else if (typeof observer === 'function') {
        observer(value);
      }
    }
  }

  error(error) {
    for (let observer of this.observers) {
      if (observer.error) {
        observer.error(error);
      }
    }
  }

  complete() {
    for (let observer of this.observers) {
      if (observer.complete) {
        observer.complete();
      }
    }
  }
}

このSubjectは、ObservableSubjectとして振る舞います。すべてのSubscriptionまたはObserverに同じ値を渡します。SubscriptionやObserverはadd和removeによって変更でき、受け取った値が同期されます。Subjectの内部にあるobservers配列に登録されたobserverのリストがあります。

各メソッドでobservers配列上で繰り返し、SubscriberまたはObserverの値を遅延コールバックで呼び出します。 next,error、さらにcompleteのように、ObservableSubjectを完了すると、新しい値またはエラーが投げられたときに、Subscriptionを解除することができます。

例えば、以下のように使うことができます。

const subject = new Subject();

const observer1 = {
  next: (value) => console.log(value * 2),
};

const observer2 = (value) => console.log(value + 2);

subject.subscribe(observer1);
subject.subscribe(observer2);
subject.next(3);
subject.complete();

// 6
// 5

observerの一つはmethodとして、もう一つはfunctionとして登録されています。.nextメソッドは遅延呼び出しになります、つまり、3が後から通知されることを意味します。最後の.complete()はSubscriptionを削除することを意味します。

注意してください、SubjectはObserverもしくはObservableの観察対象であり、自己実行するObserverではありません。 したがって、必ずしも初期化時に値を渡す必要はありません。

このように、Subjectを使用することで、Observableに複数の制御フローを追加できます。あなたは、Observableとともに、addやremove、もっと多くのカスタマイズを一緒に持つことができます。