javascript 使用RxJ的无功负载状态管理

ehxuflar  于 2023-01-24  发布在  Java
关注(0)|答案(3)|浏览(138)

这是一个经典的任务,当你有一些输入字段,你必须获取一些关于值变化的东西。让我们想象一下,我们使用角React形式。例如:

orders$ = inputControl.valueChanges.pipe(
   switchMap((value) => {
     return someService.fetch(value);
   })
);

现在我们还需要管理加载状态。我通常使用tap

orders$ = inputControl.valueChanges.pipe(
  tap(() => { loading = true }), // or loading$.next(true) if loading is a subject
  switchMap((value) => {
    return someService.fetch(value);
  }),
  tap(() => { loading = false }), // or loading$.next(false) if loading is a subject
);

然而,我们似乎可以在某种程度上避免在tap中赋值,而使用RxJ来代替,但我找不到一种方法来处理它。
对我来说,理想解决方案的用法是

orders$ = <some abstraction here that depends on inputControl.valueChanges and fetching>
loading$ = <some abstraction here that depends on fetching>
5n0oy7gb

5n0oy7gb1#

可以使用map和shareReplay操作符来实现这一点,map操作符可用于从服务调用返回值,shareReplay操作符可用于共享可观察对象并保持加载状态。

orders$ = inputControl.valueChanges.pipe(
  switchMap((value) => {
    return someService.fetch(value).pipe(
      map(data => {
        loading$.next(false);
        return data;
      }),
      startWith({loading: true})
    );
  }),
  shareReplay(1)
);
loading$ = orders$.pipe(map(data => data.loading));

这样,您可以使用orders$ observable来订阅订单,使用loading$ observable来订阅装货状态。如果您从服务调用返回一个对象,则上面的示例将不起作用,您需要将该对象 Package 在另一个具有加载属性(如{data:{},正在加载:正确/错误}

qnzebej0

qnzebej02#

看看我的库ez-state。
https://github.com/adriandavidbrand/ngx-ez/tree/master/projects/ez-state
https://adrianbrand.medium.com/angular-state-management-using-services-built-with-ez-state-9b23f16fb5ae

orderCache = new EzCache<Order[]>();

order$ = this.orderCache.value$;

loading$ = this.orderCache.loading$;

inputControl.valueChanges.subscribe(value => {
  orderCache.load(someService.fetch(value));
});

EzCache是一个美化了的行为主体,它具有方法load、保存、update和delete,并管理状态观察值,如loading$、loaded$、saving$、saved$等。
我个人会在服务中有该高速缓存,并从服务中公开可观察性,就像我写的那篇文章一样。

dly7yett

dly7yett3#

如果您将加载状态视为更大的"订单搜索请求"的一部分,那么就更容易理解如何使用RxJS创建一个发出所需总体状态的可观察对象。
你可以用一个单独的可观测量来代替两个单独的可观测量orders$loading$(* 因为它们总是在同一时间改变 *)。
我们基本上想要创建一个可观察对象,它最初发射:

{ 
    isLoading: true, 
    results: undefined
}

则在接收到结果后,发射:

{ 
    isLoading: false, 
    results: ** orders from api call ** 
}

我们可以通过使用switchMapmapstartWith来实现:
一个二个一个一个
这是一个可以运行的StackBlitz演示。

相关问题