Sapper 中的网络套接字

Websockets in Sapper

我在 Svelte 中有一个可读存储,如下所示:

const state = {};
export const channels = readable(state, set => {
        let st = state;
        let socket = new WebSocket("ws://127.0.0.1:5999");
    
        socket.onmessage = function (event) {
          var datastr = event.data.split(':');
          st[datastr[0]].value = datastr[1];
          st[datastr[0]].timestamp = Date.now();
                    set(st)
        };
          return () => {
                    socket.close()
                }
    
});

当我将它导入我的 Svelte 应用程序时,它就可以工作了。但是,如果我将 App.svelte 作为我的 index.svelte 运行 放在 Sapper 上,它一开始不起作用。它说错误 500 websocket 未定义。一旦我在浏览器中重新加载页面开始工作...... 我尝试解析一个创建商店的函数:

export const getChannel = () => {
 // here my store
return {...store}
}

然后像这样在 onMount() 中创建商店:

onMount( ()=> {
    const channel = getChannel();
});

但似乎没有成功...我错过了什么? 注意:如果只是用简单的可写替换商店,并创建 websocket onMount(),它可以正常工作。我只是想把所有的交流都放在商店里作为一个可读的...

在 Sapper 中,组件中的代码(或导入到组件中的代码)在 server-side 渲染期间在 Node 中执行,除非它被放在 onMount 中(这不会 运行 在服务器上,因为没有 'mounting' 发生)或 if (process.browser) {...} 块,或类似的东西。

这包括对 $channels 的引用导致 channels.subscribe(...) 在初始化期间被调用。

由于 Node 中没有 WebSocket 全局,创建该订阅将失败。最简单的解决方法可能是简单的功能检查:

const state = {};
export const channels = readable(state, (set) => {
  if (typeof WebSocket === 'undefined') return;

  let st = state;
  let socket = new WebSocket("ws://127.0.0.1:5999");

  socket.onmessage = function (event) {
    var datastr = event.data.split(":");
    st[datastr[0]].value = datastr[1];
    st[datastr[0]].timestamp = Date.now();
    set(st);
  };
  return () => {
    socket.close();
  };
});