在理性中,当满足某些条件时,最优雅的方法是让间隔自行清除?在JavaScript中,我可以做到:
var myInterval = setInterval(function () {
// do some stuff
if (fancyCondition) {
clearInterval(myInterval);
}
}, 1000);
在理性中,到目前为止我提出的最好的是:
let intervalIdRef = ref(None);
let clearInterval = () =>
switch (intervalIdRef^) {
| Some(intervalId) => Js.Global.clearInterval(intervalId)
| None => ()
};
let intervalId = Js.Global.setInterval(() => {
/* do some stuff */
fancyCondition ? clearInterval() : ();
}, 1000);
intervalIdRef := Some(intervalId);
有没有办法避免使用ref
?
答案 0 :(得分:3)
setInterval
/ clearInterval
本来就是可变的,但即使你的fancyCondition
也不是,所以删除ref
这里的ref
就不会你买了很多东西。我认为即使使用fancyCondition
,它也可以通过封装得到改善,并且稍微取决于您的setTimeout
,我们应该能够通过使用setInterval
而不是纯粹的功能来获得相同的行为clearInterval
/ let intervalIdRef = ref(None);
let count = ref(0);
let clearInterval = () =>
switch (intervalIdRef^) {
| Some(intervalId) => Js.Global.clearInterval(intervalId)
| None => ()
};
let intervalId = Js.Global.setInterval(() => {
if (count^ < 5) {
Js.log2("tick", count^);
count := count^ + 1;
} else {
Js.log("abort!");
clearInterval();
}
}, 200);
intervalIdRef := Some(intervalId);
。
首先,让我们通过添加计数器,打印计数,然后在达到计数5时清除间隔来使您的示例具体化,这样我们就可以使用:
clearInterval
我认为我们应该做的第一件事是将计时器状态/句柄封装在一个函数中并将let setInterval = (timeout, action) => {
let intervalIdRef = ref(None);
let clear = () =>
switch (intervalIdRef^) {
| Some(intervalId) => Js.Global.clearInterval(intervalId)
| None => ()
};
let intervalId = Js.Global.setInterval(() => action(~clear), timeout);
intervalIdRef := Some(intervalId);
};
let count = ref(0);
setInterval(200, (~clear) => {
if (count^ < 5) {
Js.log2("tick", count^);
count := count^ + 1;
} else {
Js.log("abort!");
clear();
}
});
传递给回调,而不是将它作为一个单独的函数,我们可能会多次调用知道它是否真的有效:
count
我们现在已经摆脱了全局计时器句柄,我认为它回答了你原来的问题,但我们仍然坚持使用let rec setTimeout = (timeout, action, state) => {
let continue = setTimeout(timeout, action);
let _:Js.Global.timeoutId =
Js.Global.setTimeout(() => action(~continue, state), timeout)
};
setTimeout(200, (~continue, count) => {
if (count < 5) {
Js.log2("tick", count);
continue(count + 1);
} else {
Js.log("abort!");
}
}, 0);
作为全局状态。所以,让我们摆脱它:
setInterval
在这里,我们将问题颠倒过来了。我们不是使用clearInterval
和clear
并将continue
函数传递给我们的回调,而是传递ref
函数,当我们要继续执行时,它会被调用当我们想要拯救的时候这允许我们向前传递状态,并通过使用递归来改变状态而不使用变异和package A;
my %counters;
sub new {
my ($class) = @_;
my $counter = $counters{$class} //= Counter->new;
$counter++;
return bless {} => $class;
}
sub get_counter {
my ($self_or_class) = @_;
my $class = (ref $self_or_class) || $self_or_class;
$counters{$class};
}
package B;
use parent -norequire, 'A';
。它使用更少的代码来实现这一点。我认为,如果不是你要求的那样,那就非常优雅:)