关于 websocket 和 loction.replace 的问题
Question about websocket and loction.replace
我尝试用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 代码:
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
发生错误是因为您在套接字关闭后发送消息。
当您这样做时: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
}
}
我尝试用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 代码:
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
发生错误是因为您在套接字关闭后发送消息。
当您这样做时: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
}
}