如何在多个订阅变量一起调用时仅调用一次函数
How to call function only once when multiple subscribed variables are called together
这不是一个具体的技术问题,但是我很好奇解决这个问题的最佳方法是什么?虽然我在Knockout中有这个问题,但我确信这个用例在其他地方也会有效。
假设我订阅了两个变量,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
这里有两个问题。
- 当resetAllValues()被调用时,它将所有订阅的值更改为0,包括
simpleObserve1
和simpleObserve2
。这反过来又一次又一次地调用resetAllValues()
。如何防止它进入无限循环? - 如果我想同时更新两个变量,但只调用
resetAllValues()
一次该怎么办?
我试图使用knockout的dispose()方法来帮助我,但我想知道是否有更好的方法来做到这一点。
延迟更新可能会帮助您。通过在计算对象中使用可观察对象的值,knockout创建了一个订阅。通过扩展这种计算,快速的后续变化被组合在某种微任务中。
它们可以防止循环行为,但仍然不清楚触发了多少更新。即:当设置为5
和10
时,1或2计算更新。所以我不完全确定这是否回答了你的问题。
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>
我创建了一个高阶函数acceptXParams
,它将检查参数的数量是否等于fn.length
或任意数字。否则,将不会调用原始函数:
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));
和更时尚的ES6版本acceptXParams
:
const acceptXParams = (fn, numOfParams = fn.length) =>
(...args) =>
args.length === numOfParams ? fn(...args) : undefined;
相关文章:
- 如何从模块链中调用函数.导出到节点中
- 调用函数内部的函数
- 在javascript中调用c函数
- DropDownListFor赢得't在更改时调用函数
- Javascript页面调用函数
- 在动画结束之前调用函数
- 允许父窗口在其不同域的子iframe上调用函数
- 运行Infinite Scroll后调用函数时出现问题
- JavaScript:在调用函数的文本输入上按enter键
- 使用大括号和不使用bracs调用函数的区别
- javascript在事件上调用函数
- 从index.html调用函数,该函数无限循环
- 从带参数的字符串变量调用函数中的函数
- 为什么 JS 不在滚动时调用函数
- 是否可以在不更改上下文的情况下调用函数.apply
- 如何在ES6类中使用参数调用函数
- AngularJS:调用函数时编号不更新
- JavaScript中的立即调用函数表达式(IIFE)-传递jQuery
- 在JavaScript中调用函数时自定义此选项
- 调用函数中声明的变量