我正在尝试在Svelte中throttle一个函数的执行。然而,在自动订阅中使用throttle似乎会打破它。考虑以下示例(REPL):
<script>
import throttle from 'lodash.throttle';
import { writable } from 'svelte/store';
const arr = writable(['A', 'B', 'C']);
function foo(val) {
console.log('foo: ', val);
}
</script>
{#each $arr as a}
<button on:click={throttle(() => { foo(a); }, 1000)}>
Button {a}
</button>
{/each}
foo(a)
的执行完全没有节流。如果删除{#each $arr as a}
块并仅将一个字符串传递给foo,您将看到它按预期工作。
我假设这与事件循环和Svelte自动订阅的工作方式有关,但不知道确切的原因。想知道是否有人知道a)为什么会发生这种情况,b)可能的解决方案是什么?
发布于 2021-03-30 15:42:02
如果您查看Svelte为此生成的代码,您可以看到,当您传递一个存储值时,它会在每次单击时重新生成节流函数。这将在每次单击时重置限制器计时器。
dispose = listen(button, "click", function () {
if (is_function(throttle(click_handler, 1000)))
throttle(click_handler, 1000).apply(this, arguments);
});
无论出于什么原因,在传递常规字符串时都不会发生这种情况。
dispose = listen(button, "click", throttle(click_handler, 1000));
这可能是Svelte中的一个bug,但我不确定。在GitHub repo上打开一个问题可能是值得的。
我可以通过提前生成限制函数来解决这个问题:
<script>
import throttle from 'lodash.throttle';
import { writable } from 'svelte/store';
const arr = writable(['A', 'B', 'C']);
function foo(val) {
console.log('foo: ', val);
}
$: throttledFns = $arr.map(val => getThrottled(val));
function getThrottled(val) {
console.log('getting throttled');
return throttle(() => { foo(val); }, 1000);
}
</script>
{#each $arr as a, idx}
<button on:click={throttledFns[idx]}>
Button {a}
</button>
{/each}
这将在存储数组更改时重新生成限制函数,但不是在每次单击时。
你也可以生成foo的一个限速版本并使用它,但这会限制所有对按钮的点击(例如,如果你点击A,然后点击B,那么点击B也会被限流)。
<script>
// as before
const throttledFoo = throttle(foo, 1000);
</script>
{#each $arr as a, idx}
<button on:click={() => throttledFoo(a)}, 1000)}>
Button {a}
</button>
{/each}
https://stackoverflow.com/questions/66870585
复制相似问题