如何从 Observable 计算角度信号?

问题描述 投票:0回答:1

我已经开始在我的项目中“慢慢地”接受新的 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()
绝对不是一个选择!
    

angular rxjs reactive-programming
1个回答
0
投票
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

© www.soinside.com 2019 - 2024. All rights reserved.