【问题标题】:Svelte Derived Store atomic / debounced updatesSvelte Derived Store 原子/去抖动更新
【发布时间】:2021-03-08 23:11:30
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 每次重置都会更改一个商店,因此派生商店会更新两次。然而,派生存储的输出值只有在整个更新循环运行完成后才会更新,正如您在反应日志中发现的那样。一件有趣的事情是,如果您的组件中没有任何(反应式?)对派生存储的引用,派生存储将不会运行或更新。

标签: svelte svelte-3 svelte-store


【解决方案1】:

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


对于您的情况,您可以调用一个 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);

Svelte REPL

【讨论】:

    【解决方案2】:

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

    Svelte 的 derived 允许返回回调以进行清理 (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);
    

    【讨论】:

      猜你喜欢
      • 2018-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-05
      • 2018-11-24
      • 2015-06-28
      相关资源
      最近更新 更多