【问题标题】:Question about websocket and loction.replace关于 websocket 和 loction.replace 的问题
【发布时间】:2020-05-16 17:31:19
【问题描述】:

我尝试使用Deno ws重新加载文档,但是第二次重新加载后会抛出错误
Uncaught ConnectionReset: Socket has already been closed throw new Deno.errors.ConnectionReset("Socket has already been closed");

var ws = new WebSocket("ws://127.0.0.1:8080/ws")
    ws.onopen = function () {
      ws.send('ws open')
      console.log('ws open');
    }
    ws.addEventListener("message", (e) => {
      if (e.data === 'fileUpdate') {
        // ws.send('close')
        location.replace(location.href);
      }
    })

似乎location.replace(location.href) 引发错误 有什么解决办法吗?

【问题讨论】:

  • 没有服务器端代码,是不可能重现的。请出示您的 Deno 代码。因为看起来您正在尝试关闭套接字两次。

标签: javascript websocket deno


【解决方案1】:

发生错误是因为您在 套接字关闭之后发送消息。

当你这样做时:location.replace(location.href); 刷新页面并关闭当前套接字。

您可以捕获错误,也可以在发送消息之前检查ws.isClosed

for await (const e of ws) {
  if (e === 'close') {
    ob.remove("fileUpdate")
    continue
  }
  ob.on("fileUpdate", () => {
    console.log('sending')
    if(!ws.isClosed)
       ws.send("fileUpdate")
  })
}

虽然这会修复错误,但它不会修复原因。您的 ob.on('fileUpdate') 事件在 套接字关闭后触发。您应该清除 WebSocket 关闭事件上的侦听器,您可以使用 ws.isWebSocketCloseEvent

import { acceptWebSocket, isWebSocketCloseEvent } from "https://deno.land/std@0.51.0/ws/mod.ts";
/* ... */
for await (const e of ws) {
  if(isWebSocketCloseEvent(e) || e === 'close') {
    // clear listeners here
    ob.remove("fileUpdate")
    // if e === 'close' you may want to close the socket
  }
}

【讨论】:

    【解决方案2】:

    这里是 Deno 代码:

    import { Application } from "https://deno.land/x/abc/mod.ts"; 
    import { acceptWebSocket } from "https://deno.land/std@0.51.0/ws/mod.ts";
    new Application()
      .file("/", "./index.html")
      .file("/module.js", "./module.js")
      // .file("sw.js", "ServiceWorker.js")
    
      .get('/ws', async (c: any) => {
        const { conn, headers, r: bufReader, w: bufWriter } = c.request;
        const ws = await acceptWebSocket({
          conn,
          headers,
          bufReader,
          bufWriter,
        });
        for await (const e of ws) {
          if (e === 'close') {
            ob.remove("fileUpdate")
            continue
          }
          ob.on("fileUpdate", () => {
            ws.send("fileUpdate")
          })
        }
      })
      .start({ port: 8080 })
    

    ob 像这样:

    class Ob {
      private list: ObList[] = []
      send(event: string) {
        this.list.forEach((e: ObList) => {
          if (e.event === event) {
            e.cb && e.cb()
          }
        })
      }
      on(event: string, cb: Function) {
        this.list.push({ event, cb })
      }
      remove(event:string){
        this.list=this.list.filter((e:ObList)=>{
          return e.event!==event
        })
      }
    }
    

    框架是abc

    【讨论】:

    • 该代码不起作用。没有Minimal, Reproducible Example,很难为您提供帮助。
    • 我在脚本中使用 ESmodule,如果我不重新加载它会工作
    • 该代码无法编译,请显示我们可以运行的完整服务器代码。给我发gist,我会检查一下,或者在这里更新
    • 这里是repository
    • 检查我的答案。顺便说一句,您应该使用代码更新您的问题,而不是将代码作为答案发布(除非它实际上是一个答案)
    猜你喜欢
    • 1970-01-01
    • 2013-11-25
    • 1970-01-01
    • 2019-08-17
    • 2015-03-08
    • 2019-06-11
    • 1970-01-01
    • 2013-03-28
    • 2010-11-26
    相关资源
    最近更新 更多