从 GO WebAssembly 调用 JavaScript 事件

Calling JavaScript event from GO WebAssembly

在JavaScript中events很常见,可以这样称呼:


<p id="p_id">
</p><button id="some_id">Click me</button>

var element=document.querySelector("#some_id")
var listener=element.addEventListener('click',function(event){  
     document.querySelector("#p_id").innerHTML = "Hello World";                   
 });

// OR
<p id="p_id">
<button onclick="some_function()">Click me</button>

<script>
function some_function() {
  document.querySelector("#p_id").innerHTML = "Hello World";
}

我知道对于典型的 JS 函数,我们可以在 GO 中使用 js.Global().Get().Call()js.Global().Get().Invoke(),如:

//go:build js && wasm

package main

import (
    "syscall/js"
)

var (
    document js.Value
)

func init() {
    document = js.Global().Get("document")

}

func main() {
    c := make(chan int) // channel to keep the wasm running, it is not a library as in rust/c/c++, so we need to keep the binary running
    
    alert := js.Global().Get("alert")
    alert.Invoke("Hi")    
    
    h1 := document.Call("createElement", "h1")
    h1.Set("innerText", "This is H1")
    h1.Get("style").Call("setProperty", "background-color", "blue")

    <-c
}

要从 GO 添加 eventListner,我知道我们可以这样做:

var cb js.Func
cb = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    fmt.Println("button clicked")
    cb.Release() // release the function if the button will not be clicked again
    return nil
})
js.Global().Get("document").Call("getElementById", "myButton").Call("addEventListener", "click", cb)

我正在寻找的是如何从 GO 响应 JavaScript 中触发的偶数。

更新

总结一下,我如何编写 go 代码来完成下面 JavaScript 代码的相同操作(使用 IndexedDB API):

function remove() {
    var request = db.transaction(["employee"], "readwrite")
    .objectStore("employee")
    .delete("00-03");
    
    request.onsuccess = function(event) {
       alert("Kenny's entry has been removed from your database.");
    };
 }

有什么想法吗?

如果你的 even 是一个可归因变量(例如 request.onsuccess = function() { ... }),你可以使用 Set 定义一个 js.FuncOf 来像 javascript 函数那样处理结果,类似于:

req := js.Global().Get("db").Call("transaction").Call("objectStore").Call("delete")
var f js.Func
f = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
    defer f.Release()

    js.Global().Call("alert", "Kenny's entry has been removed from your database.")
    return nil
})
req.Set("onsuccess", f)

完成后不要忘记 Release 函数 ;)