Giter Club home page Giter Club logo

Comments (8)

nhooyr avatar nhooyr commented on June 26, 2024

Unrelated to this library, see golang/go#41310

from websocket.

otaxhu avatar otaxhu commented on June 26, 2024

I don't know if you are too busy af but I found the answer and I don't know if you have the time to create an example of a ping pong websocket client compiled in WASM.

So what I did was to require a callback, passing the message as an argument, the reason is because of async nature of (*Conn) Read() method, minimal reproduction following:

//go:build js && wasm

package main

import (
	"context"
	"syscall/js"

	"nhooyr.io/websocket"
)

func main() {
	ctx := context.Background()
	conn, _, err := websocket.Dial(ctx, "ws://localhost:8080/ping-pong", nil)
	if err != nil {
		panic(err)
	}
	wr, err := conn.Writer(ctx, websocket.MessageText)
	if err != nil {
		panic(err)
	}
	js.Global().Set("sendMessageGo", js.FuncOf(func(_ js.Value, args []js.Value) any {
		// args[0] is the string that want to sent to the server
		wr.Write([]byte(args[0].String()))
		wr.Close()
		// spawning a goroutine because of conn.Read() is async, and js functions cannot wait
		go func() {
			_, bb, err := conn.Read(ctx)
			if err != nil {
				panic(err)
			}
			// args[1] is the callback, has the shape (bytes) => {/* any operation with the bytes */}
			// passing to the callback the bytes in string format
			args[1].Invoke(string(bb))
		}()
		// the js functions must return inmediatly, cannot wait for async operations
		return nil
	}))
	waitCh := make(chan struct{})
	<-waitCh
}

from websocket.

nhooyr avatar nhooyr commented on June 26, 2024

Hmm weird. I have this test here which runs in WASM and requires no extra goroutines. https://github.com/nhooyr/websocket/blob/master/ws_js_test.go

I'm def a little busy to look into exactly what's going on in your example. I'll open this up again and look into it later.

from websocket.

otaxhu avatar otaxhu commented on June 26, 2024

don't worry, I saw in the tests that you are not testing the (*Conn) .Read() method, it's only dialing to a ws server, no reading

from websocket.

nhooyr avatar nhooyr commented on June 26, 2024

No it is, see this line

err = wstest.Echo(ctx, c, 65536)

It writes a message and then confirms the same message is read back.

from websocket.

otaxhu avatar otaxhu commented on June 26, 2024

forget it, you are in fact reading in the wstest.Echo, but I think it has something to do when you are binding the Go function with the JS function

from websocket.

otaxhu avatar otaxhu commented on June 26, 2024

I tried this other example and also worked, with Promise object instead of callback for compatibility with async and await js keywords:

//go:build js && wasm

package main

import (
	"context"
	"syscall/js"

	"nhooyr.io/websocket"
)

func main() {
	ctx := context.Background()
	conn, _, err := websocket.Dial(ctx, "ws://localhost:8080/ws-chat", nil)
	if err != nil {
		panic(err)
	}

	js.Global().Set("sendMessageGo", js.FuncOf(func(_ js.Value, args []js.Value) any {
		wr, err := conn.Writer(ctx, websocket.MessageText)
		if err != nil {
			panic(err)
		}
		wr.Write([]byte(args[0].String()))
		wr.Close()
		// returning a Promise
		return js.Global().Get("Promise").New(js.FuncOf(func(_ js.Value, args []js.Value) any {

			// args[0] is resolve callback
			// args[1] is reject callback

			// spawining a goroutine because of conn.Read() blocking nature
			go func() {
				_, bb, err := conn.Read(ctx)
				if err != nil {
					// if there is an error, reject the promise, calling the reject callback
					args[1].Invoke(err.Error())
					return
				}
				// if there is no error then pass to resolve the bytes that comes from the server
				args[0].Invoke(string(bb))
			}()
			// also the constructor must return inmediatly, cannot wait for async operations
			return nil
		}))
	}))
	waitCh := make(chan struct{})
	<-waitCh
}

from websocket.

nhooyr avatar nhooyr commented on June 26, 2024

Ah yes I see, you probably can't block in a JS callback so you have to return a promise. That makes sense. We can document it for sure. See also https://www.reddit.com/r/WebAssembly/comments/nm69e8/blocking_calls_in_wasm/

from websocket.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.