Svelte Derived Store 原子/去抖动更新

Svelte Derived Store atomic / debounced updates

我一直在试验精巧的派生商店。如果您查看以下示例中的控制台日志,在递增存储 1 和存储 2 之后,然后点击重置,派生存储发出 2 个更新。

你如何使这个成为原子的或者去抖动它?例如,假设场景是派生商店根据商店 1 和 2 的组合值发出新的网络请求,如果它们一起更改,您不想触发 2 个网络请求?

https://svelte.dev/repl/a67c9d37aee348d988e8c30f60a139d9?version=3.28.0

编辑:实际上,只是添加了一个 'reactive' 控制台日志,这似乎对输出进行了去抖动(打勾?)。

我想我已经回答了我自己的问题?

派生存储的回调第二个参数是 set,它允许异步设置派生值。

import { derived } from 'svelte/store';

const delayed = derived(a, ($a, set) => {
    setTimeout(() => set($a), 1000);
});

$: console.log($delayed);

$a = 1;
// console '1' 1 second later.

API reference for derived()


对于您的情况,您可以调用最终会调用 set:

的去抖动函数
// implementing debounce yourself
let timeoutId;
const total = derived([counter1, counter2], ([c1,c2], set) => {
    if (timeoutId) {
        clearTimeout(timeoutId);
    }
    timeoutId = setTimeout(() => {
        console.log(c1, c2);
        return set(c1+c2);
    }, 1000);
}, 0);

Svelte REPL

添加到@TanLiHau 的答案中,您也可以在没有“全局”/外部范围变量的情况下执行此操作timeoutId

Svelte 的 derived 允许 return 清理回调 (https://svelte.dev/docs#derived):

If you return a function from the callback, it will be called when a) the callback runs again, or b) the last subscriber unsubscribes.

这让你可以这样写:

const total = derived([counter1, counter2], ([c1,c2], set) => {
    const timeoutId = setTimeout(() => {
        console.log(c1, c2);
        return set(c1+c2);
    }, 1000);
    
    return () => clearTimeout(timeoutId)
}, 0);