Javascript RxJS在订阅中订阅不同的观测值
我正在使用angular与ngrx store和RxJS存储和转换一些个人投资组合和适当的报价。当一个新的报价进来时,应该触发由web工作人员完成的计算。起初,我使用这段代码来达到预期的效果,但我注意到了一些缺陷Javascript RxJS在订阅中订阅不同的观测值,javascript,angular,typescript,rxjs,ngrx,Javascript,Angular,Typescript,Rxjs,Ngrx,我正在使用angular与ngrx store和RxJS存储和转换一些个人投资组合和适当的报价。当一个新的报价进来时,应该触发由web工作人员完成的计算。起初,我使用这段代码来达到预期的效果,但我注意到了一些缺陷 this.subs.sink = combineLatest([this.portfolio$, this.transactions$]) .pipe(sample(this.triggerCalculation$)) .subscribe(([portfolio, trans
this.subs.sink = combineLatest([this.portfolio$, this.transactions$])
.pipe(sample(this.triggerCalculation$))
.subscribe(([portfolio, transactions]) => {
if (!portfolio || !transactions || transactions.length === 0) {
return
}
this.worker.postMessage({ message: 'calculate positions', payload: { portfolio, transactions } })
this.subs.sink = combineLatest([
this.store.select((s) => s.performance.positionMembers),
this.store.select((s) => s.quotes.currencies),
]).subscribe(([positionMembers, currencies]) => {
if (positionMembers.length === 0 || currencies === {}) {
return
}
if (portfolio?.watchlist && positionMembers) {
this.worker.postMessage({
message: 'calculate total on static change'
})
portfolio.watchlist.all.forEach((a) => {
if (positionMembers.includes(a._id)) {
this.subs.sink = this.store
.select((s) => s.quotes.quotes[a._id])
.subscribe((q) => {
if (q?.price) {
this.worker.postMessage({
message: 'calculate performance',
payload: {
id: a._id,
quote: q,
currency: a.currency,
currencies,
baseCurrency: portfolio.baseCurrency,
},
})
}
})
}
})
}
})
})
我已经把它重构得更好了,至少我这么认为。我还改进了一些过滤功能:
this.subs.sink = this.transactions$
.pipe(
sample(this.triggerCalculation$),
withLatestFrom(this.portfolio$),
filter(([transactions, portfolio]) => portfolio?.watchlist && transactions?.length !== 0),
tap(([transactions, portfolio]) => {
this.worker.postMessage({ message: 'calculate positions', payload: { portfolio, transactions } })
}),
switchMap(([, portfolio]) => {
return combineLatest([
this.store.select((s) => s.performance.positionMembers),
this.store.select((s) => s.quotes.currencies),
of(portfolio),
]).pipe(filter(([members, currencies]) => !!members?.length && Object.keys(currencies).length !== 0))
}),
tap(() => {
this.worker.postMessage({
message: 'calculate total on static change',
})
})
)
.subscribe(([members, currencies, portfolio]) => {
portfolio.watchlist.all.forEach((a) => {
if (members.includes(a._id)) {
this.subs.sink = this.store
.select((s) => s.quotes.quotes[a._id])
.pipe(filter((q) => !!q?.price))
.subscribe((q) => {
console.warn('subscription')
this.worker.postMessage({
message: 'calculate performance',
payload: {
id: a._id,
quote: q,
currency: a.currency,
currencies,
baseCurrency: portfolio.baseCurrency,
},
})
})
}
})
})
我的最后一个问题是如何摆脱内部订阅(公文包.watchlist.all.forEach的最后一个块),在这里我创建了多个订阅。目标是拥有与报价相同数量的订阅。每次收到新的引号时,我都会更改整个对象,因此订阅整个对象会更频繁地触发。请注意,每次外部订阅触发时都会创建订阅,因此可能会有无限多个内部订阅执行相同的操作。我只需要创建一次,但它们还应该反映导致新订阅的新报价
如果一些有经验的RxJS程序员能帮助我,我会非常高兴。我从未发现一个有效的场景,其中一个订阅在另一个订阅中是一种有效的方法。每当您有一个场景需要在另一个场景中订阅时,请检查更高阶的可观察对象(如mergeMap、switchMap等)。看看这篇文章:我从来没有发现一个有效的场景,其中一个订阅在另一个订阅中是一种有效的方法。每当您有一个场景需要在另一个场景中订阅时,请检查更高阶的可观察对象(如mergeMap、switchMap等)。请看这篇文章: