检测何时不再使用 svelte store

Has*_*nka 3 javascript javascript-objects svelte svelte-component svelte-store

我正在通过环绕一个精简的可写存储来创建一个自定义的精简存储。

我想检测该商店何时未被任何组件订阅;当订阅数为0时

我的目标是清除一些在无人使用时与自定义存储绑定的大量外部资源(websockets)。

目前,我通过环绕 subscribe( ) 方法来计算订阅和取消订阅。它按预期工作。但对我来说,这看起来像是一个令人讨厌的黑客攻击。

我的问题:在 Svelte 中是否有一个标准/干净的方法来实现这种行为?

如果没有,在 Javascipt 和 svelte 方面有更多经验的人可以确认这是否合法吗?

演示:https://svelte.dev/repl/f4e24fb5c56f457a94bf9cf645955b9f ?version=3.43.1

import { writable } from 'svelte/store';

// Instanciate the store
export let store = MakeStore();

// By design, I want a function that returns a custom svelte store
export function MakeStore(initialValue = null) {

        const { subscribe, set, update } = writable(initialValue);

        let subscribercount = 0;

        let wsubscribe = function (run, callback) {
            subscribercount++;
            console.log("subscribercount++", subscribercount);

            let wunsubscribe = subscribe(run, callback);
            return () => {
                subscribercount--;
                console.log("subscribercount--", subscribercount);

                if (subscribercount == 0) {

                    // -------------------------------
                    // Free up resources
                    // I want a clean way to get here
                    // -------------------------------
                    console.log("Cleaning up...");
                }
                return wunsubscribe();
            }
        }

        // Some external calls here

        let store = {
            subscribe: wsubscribe,
            set: newvalue => {
                set(newvalue);
                // Some external calls here
            },
            update: update
        };

        // Some external calls here

        return store;
    }


Run Code Online (Sandbox Code Playgroud)

Ste*_*aes 6

是的,它内置于商店中并记录在此处

从文档

如果将函数作为第二个参数传递,则当订阅者数量从零到一(但不是从一到二等)时将调用该函数。该函数将传递一个设置函数来更改存储的值。它必须返回一个停止函数,当订户计数从一变为零时调用该函数。

所以你会这样做:

const count = writable(0, () => {
    console.log('got a subscriber');
    return () => console.log('no more subscribers');
});
Run Code Online (Sandbox Code Playgroud)

2023 年 2 月 8 日更新

请注意,上述内容适用于可读可写存储,在派生存储的情况下,您将具有以下代码:

const count = derived(items, ($items, set) => {
  console.log('got a subscriber to a derived store');
  return () => console.log('no more subscribers to derived store');
});
Run Code Online (Sandbox Code Playgroud)

no more subscribers to derived store当订阅者数量降至 0原始存储发生更改时(这是因为整个函数($items, set) => {...}再次运行),它将在此处记录。

从 v3.55.1 开始,没有内置方法可以规避此问题。