Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知

Posted

技术标签:

【中文标题】Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知【英文标题】:Knockout JS subscribe to 2 observables in a such a way that if either of the 2 change, I only get notified once 【发布时间】:2020-07-13 13:17:46 【问题描述】:

我有一个时间戳过滤器,用户可以在其中更改开始和结束时间。 哪个用户更改了 2 中的任何一个,订阅回调都可以正常工作。 但是,当用户在一种编辑模式下同时更改开始时间和结束时间时,我的订阅函数会按预期被调用两次。 我想避免这种情况,我希望它只被调用一次。关于如何实现这一目标的任何建议?

【问题讨论】:

在此处添加一些代码进行检查 【参考方案1】:

在 KO 3.4.0+ 中,您可以在依赖于 startend 的计算上使用 deferred updates,即使 startend 以互补方式更改也会导致更改方式:

let eitherX = 1;
const either = ko.computed(() => 
    start();
    end();
    return ++eitherX;
);
either.extend(deferred: true);

现场示例:

const start = ko.observable(10);
const end = ko.observable(20);
let eitherX = 1;
const either = ko.computed(() => 
    start();
    end();
    return ++eitherX;
);
either.extend(deferred: true);

console.log("Subscribing");
// Setting deferred
either.subscribe(() => console.log("notified"));
console.log("changing start");
start(11);
console.log("changing end");
end(19);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

在早期版本中,您可以使用rate limit 或0

let eitherX = 1;
const either = ko.computed(() => 
    start();
    end();
    return ++eitherX;
);
either.extend(rateLimit: 0);

现场示例:

const start = ko.observable(10);
const end = ko.observable(20);
let eitherX = 1;
const either = ko.computed(() => 
    start();
    end();
    return ++eitherX;
);
either.extend(rateLimit: 0);

console.log("Subscribing");
// Applying the rate limit
either.subscribe(() => console.log("notified"));
console.log("changing start");
start(11);
console.log("changing end");
end(19);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

您需要eitherX,这样either 的值在重新计算时总是不同的。如果您尝试根据startend(例如start() + end())定义either,如果您以互补的方式更改startend(在start 上加一并减一来自end),either 的值不会改变,您也不会收到任何通知。

【讨论】:

【参考方案2】:

当您以编程方式同时更改两个过滤器并且只希望触发一次回调时,上面的 Crowder 是正确的,当您等待用户一个接一个地更改过滤器时,这是另一回事。

在更改开始时间之后,真的无法知道用户是否会更改结束时间,那么您怎么知道等待开始时间触发器最终触发的时间?

唯一的选择是在 2 个输入过滤器之后添加一个按钮,上面写着“确认过滤器”并触发回调。

实际上,还有另一种方法,但涉及有效地执行两个回调,第一个回调在第二个触发时中途取消,这可能是您希望避免的事情,对吧?

【讨论】:

以上是关于Knockout JS 订阅 2 个 observables 的方式是,如果 2 个 observables 中的任何一个发生变化,我只会收到一次通知的主要内容,如果未能解决你的问题,请参考以下文章

使用 Knockout 订阅的循环依赖

如何使用 knockout.js 订阅变量状态更改

Knockout:从observable中删除所有订阅

Knockout.js 使每个嵌套对象都成为 Observable

在 knockout.js 中将 observable 从一个视图模型传递到另一个视图模型

Knockout JS特殊字符验证