rx js: как сделать условное суждение в наблюдаемом потоке - PullRequest
1 голос
/ 14 февраля 2020

В моем проекте Angular я описал один случай следующим образом:
В интерфейсе Frontend у меня есть языковая система, пользователь может выбрать один из вариантов. И каждый раз, когда пользователь выбирает новый язык, мне нужно вызвать с ним метод серверной стороны subscribe, и, если он успешно запущен, он вернется к subscriptionid.
В следующий раз, когда пользователь поменяет новый язык, мне нужно будет создать новую подписку. Но перед этим мне нужно unsubscribe текущий. Демонстрационный код выглядит следующим образом:

  this.start().subscribe((res) => {
    // store current subscription id   
    this.currentSubscriptionId = res.SubscriptionId;
  });

  private start(): Observable<{ [key: string]: string }> {
      return this.xService.language$.pipe(
          switchMap((language) =>
            this.unsubscribe().pipe(
              switchMap((_) => this.invoke("subscribe",language)) // this.invoke return observable<any>
            )
          )
      );
  }

  private unsubscribe(): Observable<any> {
    if (this.currentSubscriptionId) { // default initial value is empty string  ""
      return this.invoke("Unsubscribe", {
        Id: this.currentSubscriptionId
      });
    } else {
      return of("");
    }
  }

, поэтому я использую переменную состояния currentSubscriptionId для этого потока. Значение по умолчанию - пустая строка, поэтому в первый раз нет необходимости вызывать метод unsubscribe, возвращать наблюдаемую of.

В текущей реализации я инкапсулирую внутреннюю функцию logi c в unsubscribe и на основе переменной состояния currentSubscriptionId для управления потоком.

Есть ли другое оптимизированное решение для этого случая? выполните этот вид контроля в стиле Rx JS.

1 Ответ

0 голосов
/ 14 февраля 2020

Я думаю, что пришло время использовать оператор "finalize", который вызывает данную функцию по мере удаления ее подписки.

const { Subscription, BehaviorSubject, Observable, of, never, interval } = rxjs;

const Rx = rxjs.operators;

let cleanUp = new Subscription();

function start() {
  return selectedLang.pipe(
    Rx.switchMap(lang => callSubscribeAPI(lang)),
    Rx.switchMap(id =>
      never().pipe(
        Rx.startWith(id),
        Rx.finalize(() => cleanUp.add(callUnsubscribeAPI(id).subscribe()))
      )
    )
  )
}

// Mock of language selection UI:

let selectedLang = new BehaviorSubject("ja");

// Server-side API mocks:

let subscriptionIdCounter = 0;

function callSubscribeAPI(lang) {
  let id = ++ subscriptionIdCounter;
  console.log(`[server] subscribe: ${lang}@${id}`);
  return of(`${id}`);
}

function callUnsubscribeAPI(id) {
  console.log(`[server] unsubscribe: ${id}`);
  return of();
}

// Usage:

start().subscribe(console.log);

interval(300)
 .pipe(Rx.take(4))
 .subscribe(i => 
   selectedLang.next(["en", "kr", "cn", "ja"][i])
 );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.5.4/rxjs.umd.min.js"></script>
...