gpt4 book ai didi

go - syscall/js websocket回调在非阻塞行为中不响应

转载 作者:行者123 更新时间:2023-12-01 22:09:21 25 4
gpt4 key购买 nike

我有两个运行的过程,用Go语言编写,其中一个(sender.go)将消息发送到另一个(listener.go),同时通过websocket陷入for循环中。

问题是listener.go仅在终止循环后才意识到它收到了消息。

我已经尝试了几个websocket库,甚至尝试使用常规tcp流,但是在webassembly中编译时,它将不起作用,因为浏览器不支持它。尽管有这种行为,但syscall/js websocket似乎非常合适。

这是listener.go

func registerCallbacks(ws js.Value) {
ws.Call("addEventListener", "message", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
message := args[0].Get("data").String()
fmt.Println("message received ")
fmt.Println(message)
return nil
}))
}


func main() {
c := make(chan struct{}, 0)
toIP := "127.0.0.1"
toPort := 8081
ws := js.Global().Get("WebSocket").New(fmt.Sprintf("ws://%s:%d/ws", toIP, toPort))
registerCallbacks(ws)
const bigNum uint64 = 100000 * 10000
cb := func(this js.Value, args []js.Value) interface{} {
for i := uint64(0); i < bigNum; i++ {
doThings()
if i%10000000 == 0 {
fmt.Println("skimmed ten millions ")
}
}
fmt.Println("Exited for loop !!")
return nil
}
// call cb() in script of index.html from a button
js.Global().Set("cb", js.FuncOf(cb))
<-c
}

sender.go也是如此,
func main() {
toIP := "127.0.0.1"
toPort := 8081
ws := js.Global().Get("WebSocket").New(fmt.Sprintf("ws://%s:%d/ws", toIP, toPort))
time.Sleep(1 * time.Second)
fmt.Println("sending ")
ws.Call("send", js.ValueOf("msg"))
fmt.Println("Program exit ")
}

如果有人愿意重现此问题,那么这里是websocket服务器,它从发件人接收消息以将其转发给接收者,并以node.js编写,只需复制并粘贴,它就可以在多个项目中正常工作
const port = 8081;
const host = '127.0.0.1';

var WebSocketServer = require('websocket').server;
var http = require('http');

var server = http.createServer(function(request, response) {});

server.listen(port, host, () => {
console.log('WS Server is running on port ' + port + '.');
});

wsServer = new WebSocketServer({
httpServer: server
});

let sockets = [];


wsServer.on('request', function(request) {
var connection = request.accept(null, request.origin);
sockets.push(connection)
console.log("Connection with node initiated")
connection.on('message', function(message) {
console.log("message received "+message)
sockets.forEach(function(s, index, array) {
if (message.type === 'utf8') {
broadcastData = message.utf8Data
console.log("message is: "+ broadcastData)
if(s!= connection) {
console.log('send data to ' + s.socket.remotePort + ': ' + broadcastData);
s.sendUTF(broadcastData)
}
}
});
});
});

我期望listener.go在退出for循环之前收到消息

PS:使用sleep语句不是一个很好的帮助,因为当此for循环在js回调内运行时,sleep语句会产生 panic 。

最佳答案

首先,请注意,如果您正在生成wasm Go代码,则它不是多线程的,至少现在不是(2019年9月)。看
How to implement multithreading in wasm created using golang?因此,只有一个实际的执行线程。

然后,请记住,goroutines协同工作在任何可用线程上。由于只有一个线程,因此随时都只有一个goroutine运行。如果您正在运行的goroutine没有将处理器放弃给其他goroutine,则这些其他goroutine将不会运行。

您可以隐式地放弃处理器(例如,通过等待 channel 或互斥锁),也可以通过 time.Sleep runtime.Gosched 显式地放弃处理器。如果没有这样的调用,任何会注意到传入消息的goroutine将永远没有机会看到它,而您的回调(将在此goroutine或第三个goroutine中运行)将永远不会被调用。

(如果您 native 运行,而不是在wasm中运行,则通常会获得更多线程,即使在一个紧密循环中,也可以使其他CPU运行其他任务。)

关于go - syscall/js websocket回调在非阻塞行为中不响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57835979/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com