refactor(example/basic): Add documentation to examples, use wrapper func

master
ALI Hamza 2021-03-22 11:47:32 +07:00
parent 08c04bf325
commit fbc9bcdffc
Signed by: hamza
GPG Key ID: 22473A32291F8CB6
2 changed files with 96 additions and 20 deletions

@ -0,0 +1,79 @@
package main
import "syscall/js"
var (
// bridgeName is the namesace for all functions and values set.
//
// The returning JavaScript proxy via the webpack loader will look for functions and values under this namespace.
bridgeName = "__go_wasm__"
// The JS object of the __go_wasm__ value.
bridge js.Value
// Wrapper is a simple JS function that when called with a Go Function, will return a new function that will throw
// if the property `error` is an instance of JavaScript's `error`.
//
// All Go functions in the bridgeName proxy are expected to be the result of calling wrapper with the Go function.
wrapper js.Value
)
// newReturnValue creates an object with the value as the result.
// See wrapGoFunc for the reasoning behind style style of returning values from Go functions.
func newReturnValue(value interface{}) js.Value {
jsObject := js.Global().Get("Object").New()
jsObject.Set("result", value)
return jsObject
}
// newReturnError creates an object with the goError's message and creates a Javascript Error object with the message.
//
// See wrapGoFunc for the reasoning behind style style of returning values from Go functions.
func newReturnError(goErr error) js.Value {
jsObject := js.Global().Get("Object").New()
jsError := js.Global().Get("Error")
jsObject.Set("error", jsError.New(goErr.Error()))
return jsObject
}
// Using this wrapper makes it possible to throw errors in go-fashion.
// This means that all wrapped functions must return error and a value.
//
// The __wrapper__ function from JS will automatically throw if the returned object has an 'error' property.
// Inversly, it will automatically give the result value if that property exists.
// All go functions directly returned via wasm should keep this in mind.
func wrapGoFunc(f func(js.Value, []js.Value) (interface{}, error)) js.Func {
return js.FuncOf(func(this js.Value, args []js.Value) interface{} {
res, err := f(this, args)
if err != nil {
return newReturnError(err)
}
return newReturnValue(res)
})
}
func setFunc(name string, f func(js.Value, []js.Value) (interface{}, error)) {
bridge.Set(name, wrapper.Invoke(wrapGoFunc(f)))
}
func setValue(name string, value interface{}) {
bridge.Set(name, value)
}
// Toggling the __ready__ value in the bridge lets JS know that everything is setup.
// Setting __ready__ to true can help prevent possible race conditions of Wasm being called before everything is
// registered, and potentially crashing applications.
func ready() {
bridge.Set("__ready__", true)
<-make(chan bool, 0) // To use anything from Go WASM, the program may not exit.
}
// We want to make sure that this is always ran first. This means that we can make sure that whenever functions are
// initialized, they are able to be set to the bridge and wrapper.
func init() {
bridge = js.Global().Get(bridgeName)
wrapper = bridge.Get("__wrapper__")
}

@ -5,27 +5,24 @@ import (
"syscall/js"
)
func main() {
fmt.Println("Hello from go-mod-wasm!")
setup()
c := make(chan bool, 0) // To use anything from Go WASM, the program may not exit.
<-c
}
const hello = "Sample value"
func helloName(_ js.Value, args []js.Value) interface{} {
return fmt.Sprintf("Hello, %s!", args[0].String())
const hello = "Hello!"
// helloName's first value is JavaScript's `this`.
// However, the way that the JS bridge is written, it will always be JavaScript's undefined.
//
// If returning a non-nil error value, the resulting promise will be rejected by API consumers.
// The rejected value will JavaScript's Error, with the message being the go error's message.
//
// See other examples which use the Go wasm bridge api, which show more flexibility and type safety when interacting
// with JavaScript.
func helloName(_ js.Value, args []js.Value) (interface{}, error) {
return fmt.Sprintf("Hello, %s!", args[0].String()), nil
}
func setup() {
bridge := js.Global().Get("__go_wasm__")
bridge.Set("__ready__", true)
bridge.Set("hello", hello)
bridge.Set("helloName", js.FuncOf(helloName))
func main() {
fmt.Println("go-mod-wasm initialized")
js.Global()
setFunc("helloName", helloName)
setValue("hello", hello)
ready()
}