gpt4 book ai didi

javascript - RxJS:一个将自己的旧值作为输入的 Observable

转载 作者:搜寻专家 更新时间:2023-11-01 04:34:27 25 4
gpt4 key购买 nike

我正在尝试实现这样的东西:

// This obviously doesn't work, because we try to refer to `a` before it exists.
// c and m are some Observables.
const aSampled = a.pipe(
rxjs.operators.sample(c),
rxjs.operators.startWith(aInitial)
);
const a = m.pipe(
rxjs.operators.withLatestFrom(aSampled),
map(([mValue, oldAValue]) => {
// Do something.
}),
rxjs.operators.startWith(aInitial)
);

现在这显然是无法编译的废话,因为我们尝试在创建它之前对其进行采样 a,但希望它能使我的意图明确:a< 发出的每个值 应该依赖于 a 先前发出的旧值之一。 a 的旧值由 c 最后一次发射的时间决定。这有点像在 a 上调用 pairwise,只是我不想要最后两个值,而是最新的和后面的另一个值。

请注意,如果不是 startWith(aInitial) 位,这甚至不是一个定义明确的问题,因为 a 发出的第一个值将是循环定义,引用自身。但是,只要单独指定第一个值 a,该构造就具有数学意义。我只是不知道如何以干净的方式在代码中实现它。我的直觉是,通过编写某种自定义 Subject 来实现这一点会是一种冗长的方式,但更优雅的方式会非常受欢迎。

为了更具体一点,在我的用例中,我处理的是点击并拖动到平移类型的 UI 元素。 mmousemove 事件的 Observable,cmousedown 事件的 Observable。 a 将根据光标所在的位置以及点击发生时 a 的值不断变化。

最佳答案

如果我没理解错的话,基本的事件流是 mousemovemousedown

基于这些事件流,您必须计算一个新流 a,它以与 mousemove 相同的频率发出,但其数据是某些计算的结果基于鼠标的当前位置和 a 最后一次发出 mousedown 时的值。

因此,如果这是真的,我们可以使用以下 Observables 模拟 mousemovemousedown

// the mouse is clicked every 1 second
const c = interval(1000).pipe(
tap(cVal => console.log('click', cVal))
);
// the mouse moves diagonally and emits every 200 ms
const m = interval(200).pipe(
map(mVal => [mVal, mVal]),
);

我们需要的是在 mousedown 发出时以某种方式掌握 Observable a 的值。我们怎样才能得到这个?

假设我们有一个名为 value_of_aBehaviourSubject 其初始值为 1 并且保存 a。如果我们有这样的 Observable,我们可以像这样在 mousedown 发射时得到它的值

const last_relevant_a = c.pipe(       // when mousedown emits
switchMap(() => value_of_a.pipe( // the control is switched to the Observable value_of_a
take(1), // and we consider only its first value
)),
);

通过 m、mousemove Observable 和 last_relevant_a,我们拥有了所有需要的 Observable。事实上,我们只需结合他们的最新排放量,即可获得计算 a 新值所需的所有元素。

const a = combineLatest(m, last_relevant_a)
.submit(
([mouseVal, old_a_val] => {
// do something to calculate the new value of a
}
);

现在唯一要做的就是确保 value_of_a 发出 a 发出的任何值。这可以通过在 a 本身的订阅内对 value_of_a 调用 next 来完成。

将它们拼接在一起,解决方案可能是这样的

const c = interval(1000).pipe(
tap(cVal => console.log('click', cVal))
);

const m = interval(200).pipe(
map(mVal => [mVal, mVal]),
);

const value_of_a = new BehaviorSubject<number>(1);

const last_relevant_a = c.pipe(
switchMap(cVal => value_of_a.pipe(
take(1),
)),
);

const a = combineLatest(m, last_relevant_a);

a.pipe(
take(20)
)
.subscribe(
val => {
// new value of a calculated with an arbitrary logic
const new_value_of_a = val[0][0] * val[0][1] * val[1];
// the new value of a is emitted by value_of_a
value_of_a.next(new_value_of_a);
}
)

可能这也是 expand 运算符的用例,但应该对其进行调查。

关于javascript - RxJS:一个将自己的旧值作为输入的 Observable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58044470/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com