英文:
await js async function (promise) inside a go function
问题
我正在寻找将IndexDB集成到基于WASM的应用程序中。在Go函数中,如何"await"来自JavaScript函数的Promise。以下是示例:
func Get(key string) []byte {
found := js.Global().Get("Store").Call("getItem", key)
// 等待 found
// 将 js.Value 转换为 []byte
return nil
}
异步回调也可以。
附注:一个不好的解决方案是创建一个带有无限循环的Go协程,等待直到DOM变量存在,例如global.solution+ID被设置。但我认为这是一个不好的解决方案。
英文:
I am looking to integrate indexdb in a wasm based app. How do you "await" in a go function a promise from a js function. Here is the example
async getItem(key) {
try{
const out = await database.getItem(key);
return out;
}catch(err){
return null;
}
}
and in go
func Get(key string)[]byte{
found := js.Global().Get("Store").Call('getItem', key )
// await for found
// convert js.Value to to []byte
return nil
}
Async callbacks are fine too.
LE: one bad solution would be to create a go routine with an infinite loop waiting until a DOM variable exists like global.solution+ID to be set. But I believe this is a bad solution
答案1
得分: 1
你可以使用Promise
对象的then
方法来等待结果,就像这样:
package main
import (
"fmt"
"syscall/js"
)
func main() {
wait := make(chan interface{})
js.Global().Call("sayHello", 5000).Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
fmt.Println(args[0])
wait <- nil
return nil
}))
<-wait
fmt.Println("we're done here")
}
请注意,我们在Go代码中使用了一个通道来实际等待。我们需要这样做是因为Go程序在接收到来自JavaScript的回调时仍然必须保持运行状态。
index.html
文件:
<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
function sayHello(time) {
return new Promise(resolve => {
console.log('waiting %dms and resolving', time)
setTimeout(() => resolve('hola!'), time)
})
}
</script>
</head>
<body></body>
</html>
英文:
You can use the then
method from the Promise
object to wait for the result, something like this:
package main
import (
"fmt"
"syscall/js"
)
func main() {
wait := make(chan interface{})
js.Global().Call("sayHello", 5000).Call("then", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
fmt.Println(args[0])
wait <- nil
return nil
}))
<-wait
fmt.Println("we're done here")
}
Notice that we are using a channel to actually wait in the Go code. We need to do that because the Go program must still be running while receiving the callback from Javascript.
The index.html
file:
<html>
<head>
<meta charset="utf-8"/>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
function sayHello(time) {
return new Promise(resolve => {
console.log('waiting %dms and resolving', time)
setTimeout(() => resolve('hola!'), time)
})
}
</script>
</head>
<body></body>
</html>
答案2
得分: 1
承诺,真实示例(go.1.18):
type DevicesData struct {
DeviceId string
GroupId string
Kind string
Label string
}
list := make([]DevicesData, 0)
end := make(chan struct{})
// golang存在一个bug:
// enumerateDevices()返回一个数组,但是go返回一个对象。
forEach := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
data := DevicesData{
DeviceId: args[0].Get("deviceId").String(),
GroupId: args[0].Get("groupId").String(),
Kind: args[0].Get("kind").String(),
Label: args[0].Get("label").String(),
}
list = append(list, data)
// 总是返回nil
return nil
})
// promise成功函数
success := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
args[0].Call("forEach", forEach)
end <- struct{}{}
// 总是返回nil
return nil
})
failure := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
err := errors.New(args[0].Get("message").String())
// 总是返回nil
return nil
})
js.Global().Get("navigator").Get("mediaDevices").Call("enumerateDevices").Call("then", success, failure)
// 等待异步调用
<-end
这是一个使用Promise的真实示例,用于在Go语言中调用JavaScript代码。它演示了如何使用Go调用JavaScript的navigator.mediaDevices.enumerateDevices()
方法,并处理成功和失败的情况。在成功回调函数中,它使用forEach
方法遍历返回的设备列表,并将每个设备的信息存储在Go语言的DevicesData
结构中。在失败回调函数中,它创建一个错误对象并进行处理。最后,通过等待end
通道来等待异步调用的完成。
英文:
Promise, real example (go.1.18):
type DevicesData struct {
DeviceId string
GroupId string
Kind string
Label string
}
list = make([]DevicesData, 0)
end := make(chan struct{})
// golang has a bug:
// enumerateDevices() returns an array, but, go returns an object.
forEach := js.FuncOf(func(_ js.Value, args []js.Value) any {
data := DevicesData{
DeviceId: args[0].Get("deviceId").String(),
GroupId: args[0].Get("groupId").String(),
Kind: args[0].Get("kind").String(),
Label: args[0].Get("label").String(),
}
list = append(list, data)
// aways return nil
return nil
})
// promise success function
var success = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
args[0].Call("forEach", forEach)
end <- struct{}{}
// aways return nil
return nil
})
var failure = js.FuncOf(func(this js.Value, args []js.Value) interface{} {
err = errors.New(args[0].Get("message").String())
// aways return nil
return nil
})
js.Global().Get("navigator").Get("mediaDevices").Call("enumerateDevices").Call("then", success, failure)
// wait async call
<-end
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论