package bindings
import (
"syscall/js"
"github.com/fudanchii/infr"
)
type Promise[T infr.TryFromType[js.Value, T]] struct {
js.Value
}
func (p Promise[T]) forward(t string, f func(arg js.Value)) Promise[T] {
var cb js.Func
cb = js.FuncOf(func(_ js.Value, args []js.Value) any {
f(args[0])
cb.Release()
return nil
})
p.Call(t, cb)
return p
}
func (p Promise[T]) Catch(f func(arg js.Value)) Promise[T] {
return p.forward("catch", f)
}
func (p Promise[T]) Then(f func(arg js.Value)) Promise[T] {
return p.forward("then", f)
}
func (p Promise[T]) Await() (T, error) {
vchan := make(chan js.Value, 1)
echan := make(chan js.Value, 1)
p.Then(func(arg js.Value) { vchan <- arg }).
Catch(func(err js.Value) { echan <- err })
var defT T
select {
case err := <-echan:
return defT, PromiseError{err}
case v := <-vchan:
return infr.TryInto[T](v)
}
}
type PromiseError struct {
js.Value
}
func (pe PromiseError) Error() string {
if pe.Get("message").Type() == js.TypeString {
return pe.Get("message").String()
}
return pe.String()
}