观察者——获取最上次的值
Observer - get the most last value
我需要发送一个包含大量数据的请求。这些数据来自 6 个不同的组件 - 所以基本上没有 reactive approach
很难做到。我决定做一些类似 ngrx component store
的实现(由于某些原因我决定自己实现它)。
我创建了一个作为组件提供者提供的商店实现,创建了一个保存在 BehaviorSubject
中的状态,创建了一个将状态映射到所需状态的简单 select
函数数据。在 ngOnInit Parent Component
中,我向后端服务器发出请求以获取 foos
,并设置了一个 foo.isLoading
标志。然后我订阅并收听 foo.data
变化。如果是 - 我正在调用后端服务器 - 我正在设置 boo.isLoading
并且正在获取 boos
.
Foos
和 Boos
被正确获取但是 boo.isLoading
标志存在问题 - 我相信它来自调用状态观察者的顺序。步骤:
foo.isLoading 设置为 true
foo.data设置为后端响应,foo.isLoading设置为false
然后 foo observer 收到值并发出 HTTP 请求以获取 boos。
boo.isLoading 设置为 true 并发送 HTTP 请求
boo.isLoading 观察者收到 true
但是由于状态改变了两次 - boo.isLoading 观察者没有收到第一个值,而现在他们收到了,所以最后收到的值是 false
有什么解决办法吗?我已经尝试将 switchMap
状态更改为 of(state)
,因此当新值“到达”时应该取消之前的订阅,但它不起作用。
问题是您正在使用读取来触发此选择器中的写入。
this.parentStore.select(state => state.foo.data).pipe(
filter(data => !!data),
tap(_ => this.parentStore.loadBooData())
).subscribe();
并且由于 FooLoadCompletion
和 BooLoadStart
进程是同步的,执行顺序打乱了您的流程。
我会尽力解释的。
FooLoadComplete 触发以下选择器的执行,因为它们是在订阅的那一刻。
onFooLoadComplete
selector(foo.data).next(['a','b','c','d'])
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(false)
但是由于您在 foo.data 选择器中触发了 BooLoadStart
副作用,执行顺序最终变成了这样。
onFooLoadComplete
selector(foo.data).next(yourData)
BooLoadStart
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(true)
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(false)
因此 boo.isLoading
值在选择器中以您期望的相反顺序进行处理。这就是选择器打印 false
.
的原因
为避免此类问题,您应该保持 READ 和 WRITE 管道独立。
在您提供的代码中,您可以解决它删除 foo.data 选择器副作用并在 loadFooData
的 setTimeout 中调用 loadBooData
loadFooData() {
this.state.next({
...this.state.value,
foo: {
...this.state.value.foo,
isLoading: true
}
});
setTimeout(() => {
this.state.next({
...this.state.value,
foo: {
...this.state.value.foo,
isLoading: false,
data: ['a', 'b', 'c', 'd']
}
})
this.loadBooData();
}, 2000)
}
希望对你有所帮助
干杯
我需要发送一个包含大量数据的请求。这些数据来自 6 个不同的组件 - 所以基本上没有 reactive approach
很难做到。我决定做一些类似 ngrx component store
的实现(由于某些原因我决定自己实现它)。
我创建了一个作为组件提供者提供的商店实现,创建了一个保存在 BehaviorSubject
中的状态,创建了一个将状态映射到所需状态的简单 select
函数数据。在 ngOnInit Parent Component
中,我向后端服务器发出请求以获取 foos
,并设置了一个 foo.isLoading
标志。然后我订阅并收听 foo.data
变化。如果是 - 我正在调用后端服务器 - 我正在设置 boo.isLoading
并且正在获取 boos
.
Foos
和 Boos
被正确获取但是 boo.isLoading
标志存在问题 - 我相信它来自调用状态观察者的顺序。步骤:
foo.isLoading 设置为 true
foo.data设置为后端响应,foo.isLoading设置为false
然后 foo observer 收到值并发出 HTTP 请求以获取 boos。
boo.isLoading 设置为 true 并发送 HTTP 请求
boo.isLoading 观察者收到 true
但是由于状态改变了两次 - boo.isLoading 观察者没有收到第一个值,而现在他们收到了,所以最后收到的值是 false
有什么解决办法吗?我已经尝试将 switchMap
状态更改为 of(state)
,因此当新值“到达”时应该取消之前的订阅,但它不起作用。
问题是您正在使用读取来触发此选择器中的写入。
this.parentStore.select(state => state.foo.data).pipe(
filter(data => !!data),
tap(_ => this.parentStore.loadBooData())
).subscribe();
并且由于 FooLoadCompletion
和 BooLoadStart
进程是同步的,执行顺序打乱了您的流程。
我会尽力解释的。
FooLoadComplete 触发以下选择器的执行,因为它们是在订阅的那一刻。
onFooLoadComplete
selector(foo.data).next(['a','b','c','d'])
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(false)
但是由于您在 foo.data 选择器中触发了 BooLoadStart
副作用,执行顺序最终变成了这样。
onFooLoadComplete
selector(foo.data).next(yourData)
BooLoadStart
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(true)
selector(foo.isLoading).next(false)
selector(boo.isLoading).next(false)
因此 boo.isLoading
值在选择器中以您期望的相反顺序进行处理。这就是选择器打印 false
.
为避免此类问题,您应该保持 READ 和 WRITE 管道独立。
在您提供的代码中,您可以解决它删除 foo.data 选择器副作用并在 loadFooData
loadBooData
loadFooData() {
this.state.next({
...this.state.value,
foo: {
...this.state.value.foo,
isLoading: true
}
});
setTimeout(() => {
this.state.next({
...this.state.value,
foo: {
...this.state.value.foo,
isLoading: false,
data: ['a', 'b', 'c', 'd']
}
})
this.loadBooData();
}, 2000)
}
希望对你有所帮助
干杯