我已经开始在我的项目中“慢慢地”接受新的 Angular 信号。我偶然发现了以下场景,虽然它有效,但我想知道这是否是执行此操作的“Angular 方式”。 在我的组件中,我有一个缺乏初始值的信号,所以我像这样初始化它:
private readonly _id: Signal<string | undefined> = signal(undefined);
仅在
ngOnInit
上我才真正能够设置 id(例如
this._id.set('valid-id')
);
问题是我需要 id 才能执行 Http 请求。在可观察的世界中,我会朝这个方向前进:public readonly result$ = toObservable(this._id).pipe(
filter(Boolean),
switchMap((id) => this.myService.getById(id))
);
作为信号世界的新手,我会这样:
public readonly result = toSignal(
toObservable(this._id).pipe(
filter(Boolean),
switchMap((id) => this.myService.getById(id))
),
{ initialValue: [] }
);
但我担心也许我对 RxJS 和 Observables 的热爱有点偏见:)所以我想知道是否有一种 Angular 的方法可以做到这一点?也许我必须使用
compute()
或
effect()
?打电话.subscribe()
绝对不是一个选择!effect
。
import { JsonPipe } from '@angular/common';
import { HttpClient, provideHttpClient } from '@angular/common/http';
import {
Component,
DestroyRef,
OnInit,
effect,
inject,
signal,
untracked,
} from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import 'zone.js';
import { tap, timer } from 'rxjs';
@Component({
selector: 'app-root',
standalone: true,
template: `
<h1>Hello from {{ name }}!</h1>
<p>id: {{ id() }}</p>
<p>data:</p>
<pre>{{ data() | json }}<pre>
`,
imports: [JsonPipe],
})
export class App implements OnInit {
name = 'Angular';
data = signal<any>(void 0);
id = signal<number | undefined>(void 0);
url = (id: number) => `https://jsonplaceholder.typicode.com/todos/${id}`;
http = inject(HttpClient);
destroyRef = inject(DestroyRef);
constructor() {
effect(() => {
const id = this.id();
if (!id) {
return;
}
untracked(() =>
this.http
.get(this.url(id))
.pipe(tap(this.data.set), takeUntilDestroyed(this.destroyRef))
.subscribe()
);
});
}
ngOnInit() {
this.id.set(1);
timer(2000)
.pipe(
tap(() => this.id.set(2)),
takeUntilDestroyed(this.destroyRef)
)
.subscribe();
}
}
bootstrapApplication(App, { providers: [provideHttpClient()] });
源代码@stackblitz