1

我一直在尝试使用苗条的衍生商店。如果您查看以下示例中的控制台日志,在递增存储 1 和存储 2,然后单击重置后,派生存储发出 2 次更新。

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

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

编辑:实际上,只是添加了一个“反应式”控制台日志,这似乎可以消除(滴答声?)输出。

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

4

2 回答 2

2

派生商店的回调第二个参数是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 参考derived()


对于您的情况,您可以调用一个 debounce 函数,该函数最终会调用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);

苗条的 REPL

于 2020-09-27T14:02:48.513 回答
1

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

Sveltederived允许返回回调以进行清理(https://svelte.dev/docs#derived):

如果您从回调中返回一个函数,它将在 a) 回调再次运行或 b) 最后一个订阅者取消订阅时被调用。

这允许您编写如下:

const total = derived([counter1, counter2], ([c1,c2], set) => {
    const timeoutId = setTimeout(() => {
        console.log(c1, c2);
        return set(c1+c2);
    }, 1000);
    
    return () => clearTimeout(timeoutId)
}, 0);
于 2021-03-08T15:11:30.713 回答