http请求后对可观察数据进行角度排序

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

我是使用可观察量的新手,并且开始学习声明式编程。我遇到的情况是,我有一个可观察对象从 http 请求获取数据。我知道可以使用地图运算符对这些数据进行排序。

我不明白的是,如果我想根据按钮单击对这些数据进行排序(因此在http请求完成后)我怎样才能做到这一点而不需要observable再次调用http请求。我知道我可以将数据放入数组中并对其进行排序,但是是否可以仅使用可观察量/主题/行为主题等来做到这一点。

我确信这很简单,但由于我刚刚开始使用可观察值,我发现这有点令人困惑。

希望有人能指出我正确的方向。

热烈的问候

angular sorting http observable
2个回答
0
投票

我想你应该将你的http服务的响应保存为组件类属性,然后根据需要使用它。

它应该类似于:

// .ts
myData: MyDataInterface[];

ngOnInit() {
  this.httpService.getMyData()
    .subscribe(response => this.myData = response);  
}

onButtonClick() {
  this.sortMyData();
}

sortMyData() {
  this.myData = /** do sorting*/;
}

// .html
<button (click)="onButtonClick()">Sort my data</button>

0
投票

但是仅使用可观察量/主题/行为主题等就可以做到这一点吗?

是的。

由于您没有提供示例,我将进行一些假设。

假设您在 Angular 的 Init 生命周期上运行 HTTP-GET。 然后您订阅传入的响应,以对其执行某些操作。 然后,根据“按钮被单击状态”,您希望触发订阅而不触发请求,因此将排序应用于“缓存”响应。

一种方法是“mergeMap”:https://rxjs.dev/api/operators/mergeMap

   @Component({
  selector: 'app-root',
  standalone: true,
  template: `
    <h1>Hello from {{ name }}!</h1>
    <div>
        <button (click)="sort($event)"> sort</button>    
    </div>
  `,
})
export class App implements OnInit {
  public $sortEvent = new BehaviorSubject<boolean>(false); // holds the current sort state event,
  name = 'Angular';
  ngOnInit(): void {
    this.fetchSomeData() // this will only be called once
      .pipe(
        // here you merge the data of the fetch 
        // and declare that you want to use the data in a new observable
        // this new observable is the sortEvent
        // lis: is now a state within this construct, the observable before will not be triggered again
        mergeMap((lis) =>
          this.$sortEvent.pipe(map((isSorted) => (isSorted ? [...lis].sort() : lis)))
        )
      )
      .subscribe((e) => {
        // this will be triggered
        // only on the initial fetch
        // and then only when $sortEvent emits a value
        console.log(e);
      });
  }

  sort(event: Event) {
    this.$sortEvent.next(true);
  }
  // this mocks a http request
  fetchSomeData(): Observable<number[]> {
    return of([8, 2, 4, 1, 6, 1, 0]).pipe(
      tap(() => console.log('do I have been called?'))
    );
  }
}

这里需要注意的是,需要正确清理订阅。

意见建议: 尽管 Observables 和管道是处理复杂异步值的好工具,但它经常被低估,维护 mergeMaps 和 switchMaps 有多困难,以及使用这些方法创建内存泄漏的频率有多高且未被注意到。

如果 a 的值无论如何都不会改变,则应仔细考虑:

我真的需要这个东西成为可观察的吗?

我举个例子。您请求一份清单。 如果值尚未到达,则无论如何都不会显示或渲染组件。 但是您希望根据可观察到的内容显示列表,实际上该列表经常发生变化,并且当它发生变化时,应该重新渲染某些内容。

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule], 
  template: `
    <h1>Hello from {{ name }}!</h1>
    <div>
        <button (click)="sort($event)"> sort</button>
        <div>{{$maybeSortedList | async}}</div>   // use the async pipe to listen to the changing arrangements of the list
        <div>{{list }}</div>
    </div>
  `,
})
export class App implements OnInit {
  name = 'Angular';
  private $isSorted = new BehaviorSubject(false); // have a observable for a changing object
  public list: number[] = []; // have no observable for a object that changes only on init
  public $maybeSortedList = this.$isSorted.pipe(
    map((isSorted) => (isSorted ? [...this.list].sort() : this.list)), // map it to the list
  );

  ngOnInit(): void {
    this.fetchSomeData().subscribe((response) => {
      this.list = response;
    });
  }

  sort(event: Event) {
    this.$isSorted.next(true);
  }

  fetchSomeData(): Observable<number[]> {
    return of([8, 2, 4, 1, 6, 1, 0]).pipe(
      tap(() => console.log('do I have been called?'))
    );
  }
}

使用可观察对象。但不要合并、平面图、切换图超出所需范围。

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