gpt4 book ai didi

javascript - 计算链中除 combineLatest 之外的其他运算符,以避免冗余计算

转载 作者:行者123 更新时间:2023-11-29 19:09:10 25 4
gpt4 key购买 nike

我已经使用 RxJS 成功地将一个更大的 Excel 计算迁移到 JS。任何输入数据都表示为一个 Observable,当任何 Excel 公式使用多个输入时,后续计算将使用 .map.combineLatest 实现。

除了一个问题外,这很好用。这是一个简化的例子: Excel screenshot

三个输入(a$=1b$=2c$=3)用于两个不同的计算($ab = $a+$b = 3 在第一个,$bc = $b+$c = 5 在第二个)作为计算最终结果的中间步骤 $abbc = $ab + $bc = 8

当 $b 现在更新/发出新的输入值(例如 4)时,$abbc 被计算两次 - 第一次是在 $ab 更新时(导致错误的结果 $abbc =10) 并在更新 $bc 时再次生成正确的结果 12

虽然最终结果是正确的,但中间的计算既错误又多余。有什么方法可以只在 $b 更新的情况下执行最后一次计算 - 同时在 a$c$ 时仍然更新计算已更新(这将排除 zip 运算符)。我知道这个例子显然可以简化以省去中间步骤并直接从 $a$b 计算 $abbc >$c - 但在实际示例中这是不可能/不可行的。

这是JSbin中的运行示例:https://jsbin.com/pipiyodixa/edit?js,console

最佳答案

这里的问题是 RxJS 的行为在设计上是正确的。

确实应该先更新 b => ab => abbc 然后 bc => abbc。它处理流中的值。

你想要的是在“层”中处理值。abc,然后是ac , bc 然后计算最终值 abbc.

我能想到的唯一方法是利用 JavaScript 执行上下文和 setTimeout(() => {}, 0) 的技巧。这样您就不会安排任何超时(实际上是真正的 timeout might be > 0 ),而只是在 JavaScript 完成当前执行上下文后在另一个执行上下文中运行闭包。

不好的是,为了避免多次重新发出值,您需要缓存更多(因为 merge()):

var b2$ = b$.cache(1);

var ab$ = a$
.combineLatest(b2$, (a, b) => a + b)
.do(x => console.log('$a + $b = ' + x))
.cache(1);

var bc$ = b2$
.combineLatest(c$, (b, c) => b + c)
.do(x => console.log('$b + $c = ' + x))
.cache(1);

var abbc$ = new Rx.Observable.merge(ab$, bc$)
.auditTime(0)
.withLatestFrom(ab$, bc$, (_, ab, bc) => ab + bc)
.do(x => console.log('$ab + $bc = ' + x));

console.log("Initial subscription:")
abbc$.subscribe();

b$.next(4);

auditTime()运算符(operator)是这里最重要的事情。它触发 withLatestFrom() 来更新它的值,而当它第一次被 ab$bc$ 触发时,它会忽略所有连续的发射,直到此闭包执行结束(这是 setTimeout() 技巧)。

查看现场演示:https://jsbin.com/zoferid/edit?js,console

此外,如果您添加 a$.next(5);,最终计算只会执行一次(这可能是好是坏 :))。

我不知道这是否能解决您的问题,因为正如我所说,RxJS 就是这样工作的。我还没有在任何更复杂的示例中对其进行测试,所以这可能不是您最终可以使用的方式。

请注意,cache() 运算符已在 RC.1 中删除,目前没有替代品:https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md

关于javascript - 计算链中除 combineLatest 之外的其他运算符,以避免冗余计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40455579/

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