Как мне запустить событие внутри приложения Angular10 с помощью RxJS?

#angular #rxjs

#angular #rxjs

Вопрос:

Я начинаю с Angular10. Я написал холст и могу рисовать на нем. Давайте назовем то, что я рисую на холсте, Foobar — мой код рисования Angular10 в Foobars работает нормально. Я получаю Foobar от вызова REST с использованием HttpClient, и это тоже работает нормально, потому что оно заполняет это.foobar, когда я выполняю вызов REST. Что я хочу сделать, так это заставить холст наблюдать за этим.foobar ‘model’, чтобы при этом.foobar изменяется, затем Canvas перерисовывает Foobar.

Означает ли это, что я делаю Foobar наблюдаемым с помощью RxJS? Если да, то как мне это сделать? Затем это.foobar.subscribe(()=> {this.canvas.drawFoobar()}). Как мне сделать Foobar наблюдаемым? Нужно ли расширять класс Foobar Typescript?

Как только я получу «прослушивание» работы Foobar (я хороший программист Java Swing), как мне запустить событие изменения Foobar вручную? Предположим, я модифицирую Foobar и хочу запустить событие modelChanged (например, в Swing), каков шаблон для этого в RxJS?

Пожалуйста, дайте мне несколько советов и помогите мне двигаться в правильном направлении. Есть ли блог, в котором RxJS объясняется с использованием концепций прослушивания Java Swing? Спасибо и очень признателен!

Комментарии:

1. Используйте тему . this.foobar = new Subject<any>();

Ответ №1:

Subjects — это наиболее распространенный способ преобразования обязательного фрагмента кода RxJS в функциональные потоки RxJS. Объекты являются как наблюдателями, так и наблюдаемыми, поэтому вы можете императивно писать subject.next(value) , а также subject.subscribe(value => {..})

Вот наивный шаблон, который превращает свойство в поток. Здесь вы бы этого не subscribe сделали foobar , вместо этого вы можете subscribe _foobar использовать значение, BehaviorSubject представляющее значения, установленные для свойства foobar

 private _foobar$ = new BehaviorSubject<Foobar>(new Foobar(/*default*/));

get foobarProp(): Foobar {
  return this._foobar$.value
}

set foobarProp(val: Foobar): void {
  this._foobar$.next(val);
}
  

this._foobar.next(val); не ограничивается функцией установки. Вы можете написать это где угодно.

Ответ №2:

Спасибо! Я, ты заставил меня двигаться в правильном направлении, и я заставил это работать. Для других с той же задачей это мое решение (простите за плохой машинописный текст, я начинаю):

app.component.ts

 import { Component,OnInit, ViewChild } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { ApiService } from './api.service';
import { CanvasComponent } from './canvas/canvas.component';
import { Foobar } from './foobar';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'FOOOBAR';

  foobarSubject:BehaviorSubject<Foobar>;
  @ViewChild(CanvasComponent) canvasComponent:CanvasComponent;

  constructor(private apiService: ApiService) {
  }

  ngOnInit() {
    console.log("ngInit() called");
    this.foobarSubject= new BehaviorSubject<Forbar>(null);
    this.registerFoobar();
  }

  go() {
    this.foobarSubject.subscribe(
      (data:Foobar) => {
        if (data != null) {
          console.log("foobar was not null, updating canvas");          
          this.canvasComponent.update(data);
        }
      }
    );
  }

  // Register the callback containing the REST call 
  // so that it loads the next Foobar in the foobarSubject
  registerFoobar() {
    console.log("getting foobar");
    this.apiService.getFoobarObservable().subscribe(
      (foobar:Foobar) => {this.foobarSubject.next(foobar)},
      (err) => console.error(err),
      () => console.log("foobar:   this.foobarSubject.value.toString())
    );
  }
}
  

app.component.html

 <h1>Hello {{title}}</h1>
<app-canvas></app-canvas>

<button mat-button matSuffix mat-icon-button aria-label="Go" title="Go"
(click)="go()">GO</button>
  

app.service.html

 import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Foobar } from './foobar';

    const remoteUrl = 'http://localhost:8080/foobar;
    
    @Injectable({
      providedIn: 'root'
    })
    export class ApiService {
    
      constructor(private http: HttpClient) { }
    
      getFoobarObservable(): Observable<Foobar> {
        return this.http.get<Foobar>(remoteUrl);
      }
    }