add WASM blazor-like thing
This commit is contained in:
77
go/wasmruntime/fetch.go
Normal file
77
go/wasmruntime/fetch.go
Normal file
@@ -0,0 +1,77 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package wasmruntime
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// Fetch performs an HTTP GET via the browser Fetch API and returns the response
|
||||
// body as a string. It bridges a JS Promise into Go: it registers then/catch
|
||||
// callbacks and blocks the calling goroutine on a channel until the request
|
||||
// settles.
|
||||
//
|
||||
// Because it blocks, call it from a goroutine — never from a reactive callback
|
||||
// or event handler — and write the result into signals when it returns, e.g.:
|
||||
//
|
||||
// go func() {
|
||||
// body, err := Fetch(url)
|
||||
// ...
|
||||
// data.Set(...) // updates the UI reactively
|
||||
// }()
|
||||
func Fetch(url string) (string, error) {
|
||||
var (
|
||||
once sync.Once
|
||||
done = make(chan struct{})
|
||||
body string
|
||||
ferr error
|
||||
onResp, onText, onErr js.Func
|
||||
)
|
||||
finish := func() { once.Do(func() { close(done) }) }
|
||||
|
||||
onErr = js.FuncOf(func(this js.Value, args []js.Value) any {
|
||||
msg := "fetch error"
|
||||
if len(args) > 0 && args[0].Truthy() {
|
||||
e := args[0]
|
||||
if m := e.Get("message"); m.Truthy() {
|
||||
msg = m.String()
|
||||
} else {
|
||||
msg = e.Call("toString").String()
|
||||
}
|
||||
}
|
||||
ferr = errors.New(msg)
|
||||
finish()
|
||||
return nil
|
||||
})
|
||||
|
||||
onText = js.FuncOf(func(this js.Value, args []js.Value) any {
|
||||
if len(args) > 0 {
|
||||
body = args[0].String()
|
||||
}
|
||||
finish()
|
||||
return nil
|
||||
})
|
||||
|
||||
onResp = js.FuncOf(func(this js.Value, args []js.Value) any {
|
||||
resp := args[0]
|
||||
if !resp.Get("ok").Bool() {
|
||||
ferr = fmt.Errorf("HTTP %d", resp.Get("status").Int())
|
||||
finish()
|
||||
return nil
|
||||
}
|
||||
// resp.text() -> Promise<string>
|
||||
resp.Call("text").Call("then", onText).Call("catch", onErr)
|
||||
return nil
|
||||
})
|
||||
|
||||
js.Global().Call("fetch", url).Call("then", onResp).Call("catch", onErr)
|
||||
|
||||
<-done
|
||||
onResp.Release()
|
||||
onText.Release()
|
||||
onErr.Release()
|
||||
return body, ferr
|
||||
}
|
||||
Reference in New Issue
Block a user