Установка переменной с помощью оператора касания Rx Js - PullRequest
2 голосов
/ 24 апреля 2020

У меня были трудности с установкой переменной awaiting_response (ниже) в true (она не устанавливается) с использованием tap() из Rx Js.

Было найдено хакерское решение установив за пределы pipe(), но я представляю, что это не идеально.

Тот же код можно посмотреть здесь

Вот component.ts

import { Component, OnInit } from "@angular/core";
import { Observable, Subject, of } from "rxjs";
import { debounceTime, distinctUntilChanged, tap, switchMap, catchError, finalize } from "rxjs/operators";
import { ServiceApiService, ITemp } from "./service-api.service";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
  protected addresses: Observable<ITemp[]>;
  private search_term: Subject<string> = new Subject<string>();
  protected executing_search: boolean = false;
  protected awaiting_response: boolean = false;

  constructor(private search: ServiceApiService) {}

  ngOnInit() {
    this.addresses = this.search_term.pipe(
      debounceTime(3500),
      distinctUntilChanged(),
      tap(() => (this.awaiting_response = true)),
      tap(() => () => console.log("awaiting", this.awaiting_response)),
      switchMap((term: string) =>
        this.search.search_addresses(term).pipe(
          catchError(() => of<ITemp[]>([]))
          //finalize(() => setTimeout(() => (this.awaiting_response = false), 0))
        )
      ),
      tap(() => (this.awaiting_response = false)),
      tap(() => console.log("awaiting", this.awaiting_response)),
      tap(() => (this.executing_search = false))
      //finalize(() => (this.awaiting_response = false))
    );
  }

  execute_search() {
    this.executing_search = true;
    this.search_term.next("term");
  }
}

service

import { Injectable } from "@angular/core";
import { Observable, Subscriber } from "rxjs";

export interface ITemp {
  value: string;
}

@Injectable({
  providedIn: 'root',
})
export class ServiceApiService {
  constructor() {}

  search_addresses(term: string): Observable<ITemp[]> {
    return Observable.create((observer: Subscriber<any>) => {
      observer.next([{ value: `response: ${new Date().toString()}` }]);
      observer.complete();
    });
  }
}

И component.html

<button (click)="execute_search()">Search</button>
<div>Awaiting: {{awaiting_response | json}}</div>
<div>Executing {{executing_search | json}}</div>
<div>Response: {{addresses | async | json}}

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Вы просто не видите журнал, замените

tap(() => () => console.log("awaiting", this.awaiting_response))

на

tap(() => console.log("awaiting", this.awaiting_response))
1 голос
/ 24 апреля 2020

Короткий ответ: ваш код должен работать как положено.

Вот объяснение. Ваш awaiting_response имеет значение true, но вы не сможете увидеть разницу, поскольку observer в вашем сервисе мгновенно передает значения

Чтобы показать разницу, я установил timeout в обслуживание, как показано ниже,

search_addresses(term: string): Observable<ITemp[]> {
    return Observable
    .create((observer: Subscriber<any>) => {
      setTimeout(() => {
        observer.next([{ value: `response: ${new Date().toString()}` }]);
        observer.complete();
      }, 3000);
    });
}

Вы можете увидеть разницу в этом stackblitz

...