javascript 如何解决在客户端订阅之前发布状态更新的问题

xdnvmnnf  于 2023-05-16  发布在  Java
关注(0)|答案(1)|浏览(118)

所以我正在探索一个新的框架,可以用来在后端编写React / TSX组件。
我正在实现几个基本的例子,展示如何使用钩子来钩住组件的生命周期。
当使用useClientEffect钩子实现视图计数器时会出现这个问题。
假设以下服务器端组件

export const ViewCounter = (props, { key, initiator }: RenderOptions) => {
    const [views, setViews] = useState(0, {
        key: 'views',
        scope: Scopes.Global,
    });
    const [clients, setClients] = useState(0, {
        key: 'clients',
        scope: Scopes.Global,
    });

    useClientEffect(() => {
        if (initiator !== Initiator.RenderClient) return;
        setClients(clients + 1);
    }, []);

    useClientEffect(() => {
        if (initiator !== Initiator.RenderClient) return;
        setViews(views + 1);
    });

    return (
        <ServerSideProps key={`${key}-props`} views={views} clients={clients} />
    );
};

每次在连接的客户端上下文中在服务器上呈现组件时,都会调用useClientEffect。它类似于前端的useEffect,但是当服务器组件在客户端被使用/呈现时,它会在服务器端被调用。
该组件/问题可在https://state-less.cloud上实时查看
当页面被加载并且ViewCounter组件被呈现在客户端时,传递给useClientEffect的回调将被调用,这将使计数器增加1。这反过来又会导致组件的重新呈现,其中它将更新的状态发布到所有 * 订阅的 * 客户端。
但是,客户端还没有订阅更改,因为服务器端的重新呈现发生在客户端可以将其订阅发送到组件之前。
这是因为在不呈现组件的情况下,我不知道PubSub订阅密钥。我不能预先计算它,因为组件可能有动态计算的键。
这会导致加载页面的客户端接收到过期状态的问题,因为它没有接收到对它刚刚呈现的组件的任何更新。

在图片中,您可以看到计数是10,但实际上服务器上是11。现在假设第二个用户打开同一个页面,计数器再次增加1。
这导致计数器跳2而不是增加1,因为它现在接收实际的实时值,因为它订阅了组件的更改。


所以问题是当前连接的客户端是一个状态更新后,而所有先前连接的客户端接收更新的状态。

我如何以一种干净的方式解决这个问题?

我想我可以以某种方式记录最后几秒钟的状态更新,并将它们传输给新订阅的客户端,如果我能弄清楚他是否收到了它。
但这使得整个事情有点过于管理。如果有大量的状态更新,它也会增加内存使用。
我相信这件事已经解决了,我只是不知道该怎么办。

x7yiwoj4

x7yiwoj41#

一个可能的解决方案是提供另一个生命周期事件,一旦客户端订阅了任何更新,该事件就会被执行。
您可以针对不同的生命周期事件多次调用useClientEffect,而不是只调用一次。当组件安装到客户端时再次调用它,并将setViews调用移动到生命周期事件,一旦客户端订阅了更改,就会执行该事件。

相关问题