RxJS-サブジェクトの操作

サブジェクトは、マルチキャストできる、つまり多くのオブザーバーと話すことができるオブザーバブルです。イベントリスナーのあるボタンを考えてみましょう。ユーザーがボタンをクリックするたびに、リスナーの追加を使用してイベントにアタッチされた関数が呼び出されます。同様の機能が件名にも適用されます。

この章では、次のトピックについて説明します。

  • 件名を作成する
  • ObservableとSubjectの違いは何ですか?
  • 行動主体
  • 件名を再生
  • AsyncSubject

件名を作成する

サブジェクトを操作するには、以下に示すようにサブジェクトをインポートする必要があります-

import { Subject } from 'rxjs';

次のようにサブジェクトオブジェクトを作成できます-

const subject_test = new Subject();

オブジェクトは、3つのメソッドを持つオブザーバーです-

  • next(v)
  • error(e)
  • complete()

件名を購読する

以下に示すように、件名に複数のサブスクリプションを作成できます-

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});

サブスクリプションは、前に説明したaddlistenerと同じように、サブジェクトオブジェクトに登録されます。

サブジェクトへのデータの受け渡し

next()メソッドを使用して作成されたサブジェクトにデータを渡すことができます。

subject_test.next("A");

データは、サブジェクトに追加されたすべてのサブスクリプションに渡されます。

ここに、主題の実用的な例があります-

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.next("B");

subject_testオブジェクトは、新しいSubject()を呼び出すことによって作成されます。subject_testオブジェクトには、next()、error()、およびcomplete()メソッドへの参照があります。上記の例の出力を以下に示します-

出力

以下に示すように、complete()メソッドを使用してサブジェクトの実行を停止できます。

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(`From Subject : ${v}`)
});
subject_test.subscribe({
   next: (v) => console.log(`From Subject: ${v}`)
});
subject_test.next("A");
subject_test.complete();
subject_test.next("B");

completeを呼び出すと、後で呼び出される次のメソッドは呼び出されません。

出力

error()メソッドを呼び出す方法を見てみましょう。

以下は実際の例です-

import { Subject } from 'rxjs';

const subject_test = new Subject();

subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.subscribe({
   error: (e) => console.log(`From Subject : ${e}`)
});
subject_test.error(new Error("There is an error"));

出力

ObservableとSubjectの違いは何ですか?

オブザーバブルは、サブスクライバーと1対1で話します。observableをサブスクライブするときはいつでも、実行は最初から開始されます。ajaxを使用して行われたHttp呼び出しを行い、2人のサブスクライバーがobservableを呼び出します。ブラウザのネットワークタブに2つのHttpHttpリクエストが表示されます。

これが同じの実例です-

import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber1 = final_val.subscribe(a => console.log(a));
let subscriber2 = final_val.subscribe(a => console.log(a));

出力

ここで問題となるのは、同じデータを共有したいのですが、2回のHttp呼び出しを犠牲にして共有したくないということです。1回のHttp呼び出しを行い、サブスクライバー間でデータを共有したいと考えています。

これは、サブジェクトを使用して可能になります。マルチキャストできる、つまり多くのオブザーバーと話すことができるオブザーバブルです。サブスクライバー間で値を共有できます。

これはSubjectsを使用した実際の例です-

import { Subject } from 'rxjs';
import { ajax } from 'rxjs/ajax';
import { map } from 'rxjs/operators';

const subject_test = new Subject();

subject_test.subscribe({
   next: (v) => console.log(v)
});
subject_test.subscribe({
   next: (v) => console.log(v)
});

let final_val = ajax('https://jsonplaceholder.typicode.com/users').pipe(map(e => e.response));
let subscriber = final_val.subscribe(subject_test);

出力

これで、1つのHttp呼び出しのみが表示され、呼び出されたサブスクライバー間で同じデータが共有されます。

行動主体

行動サブジェクトは、呼び出されたときに最新の値を提供します。

以下に示すように行動サブジェクトを作成できます-

import { BehaviorSubject } from 'rxjs';
const subject = new BehaviorSubject("Testing Behaviour Subject"); 
// initialized the behaviour subject with value:Testing Behaviour Subject

これは、BehaviorSubjectを使用するための実用的な例です-

import { BehaviorSubject } from 'rxjs';
const behavior_subject = new BehaviorSubject("Testing Behaviour Subject"); 
// 0 is the initial value

behavior_subject.subscribe({
   next: (v) => console.log(`observerA: ${v}`)
});

behavior_subject.next("Hello");
behavior_subject.subscribe({
   next: (v) => console.log(`observerB: ${v}`)
});
behavior_subject.next("Last call to Behaviour Subject");

出力

件名を再生

replaysubjectは動作subjectに似ており、値をバッファリングして、新しいサブスクライバーに対して同じものを再生できます。

これがリプレイサブジェクトの実例です-

import { ReplaySubject } from 'rxjs';
const replay_subject = new ReplaySubject(2); 
// buffer 2 values but new subscribers

replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject A: ${v}`)
});

replay_subject.next(1);
replay_subject.next(2);
replay_subject.next(3);
replay_subject.subscribe({
   next: (v) => console.log(`Testing Replay Subject B: ${v}`)
});

replay_subject.next(5);

使用されるバッファ値は、再生対象で2です。したがって、最後の2つの値はバッファリングされ、呼び出される新しいサブスクライバーに使用されます。

出力

AsyncSubject

AsyncSubjectの場合、最後に呼び出された値がサブスクライバーに渡され、complete()メソッドが呼び出された後にのみ実行されます。

これは同じの実用的な例です-

import { AsyncSubject } from 'rxjs';

const async_subject = new AsyncSubject();

async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject A: ${v}`)
});

async_subject.next(1);
async_subject.next(2);
async_subject.complete();
async_subject.subscribe({
   next: (v) => console.log(`Testing Async Subject B: ${v}`)
});

ここで、completeが呼び出される前に、サブジェクトに渡される最後の値は2であり、サブスクライバーに渡される値と同じです。

出力