angular - Sätta variabel med RxJs tap-operatorn


Jag har haft svårigheter med att sätta variabeln awaiting_response (nedan) till true (den sätts inte), med användning av tap() från RxJs.

En hackig lösning gjordes genom att sätta utanför pipe() men jag antar att det inte är idealiskt.

Samma kod kan ses här

Här är 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");
  }
}

Tjänsten

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();
    });
  }
}

Och 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}}

Svar #1

Du kan bara inte se stocken, byt ut

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

till

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

Svar #2

Kort svar är att din kod borde fungera som förväntat.

Här är förklaringen. Ditt awaiting_response sätts till true men du kommer inte kunna se skillnaden eftersom observer i din tjänst skickar värden direkt

För att visa skillnaden har jag satt en timeout i tjänsten som nedan,

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

du kan se skillnaden i denna stackblitz

Relaterade artiklar