[英]How to call function only once when multiple subscribed variables are called together
This is not specifically a technical question but I was curious what is the best approach to such a problem? 这不是一个特别的技术问题,但我很好奇这个问题的最佳方法是什么? Although I have this issue in Knockout, I'm sure the use case will be valid elsewhere too.
虽然我在Knockout中有这个问题,但我确信用例在其他地方也是有效的。
Lets say I have subscribed 2 variables, simpleObserve1
, simpleObserve2
so that every time their value changes, they call a function resetAllValues()
. 假设我已经订阅了2个变量
simpleObserve1
, simpleObserve2
这样每次它们的值发生变化时,它们都会调用一个函数resetAllValues()
。
var simpleObserve1 = ko.observable(0), // initial values
simpleObserve2 = ko.observable(0); // initial values
var resetAllValues = function resetAllValues() {
/* this function takes all observable values and resets them */
{...}
}
simpleObserve1.subscribe(function(){
resetAllValues();
});
simpleObserve2.subscribe(function(){
resetAllValues();
});
simpleObserve1(5); // value changed anywhere in code
simpleObserve2(10); // value changed anywhere in code
2 questions here. 这里有2个问题。
simpleObserve1
and simpleObserve2
. simpleObserve1
和simpleObserve2
。 This in turn calls resetAllValues()
over and over again. resetAllValues()
。 How do I prevent this from going into an infinite loop? resetAllValues()
only once? resetAllValues()
怎么办? I've tried to use the knockout's dispose() method to help me along, but I was wondering if there is a better way to do this. 我试图使用knockout的dispose()方法帮助我,但我想知道是否有更好的方法来做到这一点。
Deferred Updates might help you out. 延期更新可能会帮助您。 By using observables' values in a computed, knockout creates a subscription.
通过在计算中使用observables的值,knockout创建订阅。 By extending this computed, rapidly succeeding changes are combined in some sort of micro-task.
通过扩展这个计算,快速成功的变化被组合在某种微任务中。
They prevent the looping behavior, but it's still kind of unclear how many updates are triggered. 它们可以防止循环行为,但仍然不清楚触发了多少更新。 Ie: when setting to
5
and 10
results in 1 or 2 computed updates. 即:当设置为
5
和10
产生1或2个计算更新。 So I'm not entirely sure if this answers your question. 所以我不完全确定这是否能回答你的问题。
var i = 0, simpleObserve1 = ko.observable(0), // initial values simpleObserve2 = ko.observable(0); // initial values ko.computed(function resetAllValues() { console.log("Set " + ++i + ", before:"); console.log("1: ", simpleObserve1()); console.log("2: ", simpleObserve2()); simpleObserve1(0); simpleObserve2(0); console.log("Set " + i + ", after:"); console.log("1: ", simpleObserve1()); console.log("2: ", simpleObserve2()); }).extend({ deferred: true }); simpleObserve1(5); // value changed anywhere in code simpleObserve2(10); // value changed anywhere in code
.as-console-wrapper { min-height: 100%; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
I've created a higher order function acceptXParams
, that will check if the number of params is equal to fn.length
or an arbitrary number. 我创建了一个更高阶函数
acceptXParams
,它将检查params的数量是否等于fn.length
或任意数字。 If not, the original function won't be invoked: 如果不是,则不会调用原始函数:
function acceptXParams(fn, numOfParams) { var numOfParams = numOfParams === undefined ? fn.length : numOfParams; return function() { if(arguments.length !== numOfParams) { return; } return fn.apply(fn, arguments); } } /** example **/ function sum(a, b, c) { return a + b + c; } var sum3 = acceptXParams(sum); console.log(sum3(1, 2, 3)); console.log(sum3(1, 2)); console.log(sum3(1, 2, 3, 4));
And a more sleek ES6 version acceptXParams
: 更时尚的ES6版本
acceptXParams
:
const acceptXParams = (fn, numOfParams = fn.length) =>
(...args) =>
args.length === numOfParams ? fn(...args) : undefined;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.