use*_*051 5 javascript rxjs reactivex
我正在尝试实现这样的事情:
// 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)
);
Run Code Online (Sandbox Code Playgroud)
现在这显然是无法编译的废话,因为我们sample a在创建它之前就尝试这样做,但是希望它使我的意图很明确:每个发出的值a都应依赖于之前发出的旧值之一a。的哪个旧值a由上次c发出某种东西的时间决定。这有点像调用pairwise上a,但我不希望最后两个值,而是从更靠后的最新和另一个。
请注意,如果不是startWith(aInitial)位,这甚至不是一个定义明确的问题,因为by发出的第一个值a将循环引用其自身来定义。但是,只要a分别指定第一个值,该构造就具有数学意义。我只是不知道如何以干净的方式在代码中实现它。我的直觉是,通过编写某种自定义主题可以有一种long回的方式,但是更优雅的做法将是非常受欢迎的。
为了使这一点更加具体,在我的用例中,我处理的是UI元素的单击并拖动到平移类型。m是mousemove事件的可观察性,c是事件的可观察性mousedown。a然后,它将根据光标所在的位置以及a单击事件发生时的值不断变化。
如果我理解正确的话,基本的事件流是mousemove和 a mousedown。
基于这些事件流,您必须计算一个新的流a,它以相同的频率发出mousemove,但其数据是基于鼠标当前位置和a上次mousedown发出时的值进行某些计算的结果。
因此,如果这是真的,我们可以使用以下 Observablesmousemove进行模拟mousedown
// 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]),
);
Run Code Online (Sandbox Code Playgroud)
a我们需要的是在发出时以某种方式掌握 Observable 的值mousedown。我们怎样才能得到这个?
假设我们有一个BehaviourSubject被调用者value_of_a,其初始值为1且保存值a。mousedown如果我们有这样的 Observable,我们可以像这样简单地在发出时获取它的值
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
)),
);
Run Code Online (Sandbox Code Playgroud)
有了mmousemove 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
}
);
Run Code Online (Sandbox Code Playgroud)
现在唯一要做的就是确保value_of_a发出 发出的任何值a。这可以通过在其自身的订阅内next调用来完成。value_of_aa
将它们缝合在一起,解决方案可能是这样的
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);
}
)
Run Code Online (Sandbox Code Playgroud)
也许这也是expand操作员的一个用例,但应该进行调查。
| 归档时间: |
|
| 查看次数: |
121 次 |
| 最近记录: |