区间清理原因

时间:2018-05-16 15:10:19

标签: functional-programming reason bucklescript

在理性中,当满足某些条件时,最优雅的方法是让间隔自行清除?在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

1 个答案:

答案 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

在这里,我们将问题颠倒过来了。我们不是使用clearIntervalclear并将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'; 。它使用更少的代码来实现这一点。我认为,如果不是你要求的那样,那就非常优雅:)