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