在不重新计算映射值的情况下在 rxjs 中共享组合 Observables

Sharing combine Observables in rxjs without recalculating mapped values

不太确定如何提出这个问题,但我正在尝试将一个事件与多个其他事件结合起来,共享事件的管道只计算一次(以避免不必要的计算或切断请求)

这是我要解决的问题的一个例子:

import {
  fromEvent,
  combineLatest,
  map
} from 'rxjs';
import Emitter from 'events'

const emitter = new Emitter()

const shared = fromEvent(emitter, 'shared')
const specific1 = fromEvent(emitter, '1')
const specific2 = fromEvent(emitter, '2')

const pipe = shared.pipe(
  map(() => {
    const calculatedValue = Math.random()
    // This function is called twice, instead of once
    console.log(`calculation performed: ${calculatedValue}`)
    return calculatedValue
  })
)

/**
 * @param {import('rxjs').Observable<any>} observable 
 */
const combine = (observable) => {
  combineLatest([pipe, observable]).subscribe(console.log)
}

combine(specific1)
combine(specific2)

console.log('Emitting shared event')
emitter.emit('shared')
// logs: "calculation performed: [random value]
// logs: "calculation performed: [a different random value]

console.log('Emitting event 1')
emitter.emit('1')
// uses the first random number

console.log('Emitting event 2')
emitter.emit('2')
// uses the second random number

第一个和第二个合并的 observables 现在使用两个不同的值,尽管我希望它们使用相同的值。有没有一种方法可以确保 map 函数只被调用一次,同时仍然使用 rxjs 函数(即避免用计算值编写变量)

你可以看到另一个例子here, using html buttons

您可以使用shareReplay

const pipe = sharedEvent.pipe(
  map(() => {
    const val = randomNumber()
    addToFeed(`Shared event executed, calculated value ${val}`)
    return val
  }),
  shareReplay()
)