-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
promise.go
87 lines (78 loc) · 1.87 KB
/
promise.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package promise
import (
"syscall/js"
"zenhack.net/go/jsapi"
"zenhack.net/go/util/orerr"
"zenhack.net/go/util/thunk"
)
type Promise[T ~jsapi.ValueKind] struct {
Value js.Value
}
func New[T ~jsapi.ValueKind](use func(resolve func(T), reject func(error))) Promise[T] {
var useJs js.Func
useJs = js.FuncOf(func(this js.Value, args []js.Value) any {
defer useJs.Release()
use(
func(result T) {
args[0].Invoke(jsapi.Value(result).Value)
},
func(err error) {
args[1].Invoke(jsapi.WrapError(err))
},
)
return nil
})
return Promise[T]{
Value: js.Global().Get("Promise").New(useJs),
}
}
func Resolve[T ~jsapi.ValueKind](v T) Promise[T] {
return Promise[T]{
Value: js.Global().Get("Promise").Call("resolve", jsapi.Value(v).Value),
}
}
func Then[A, B ~jsapi.ValueKind](
pa Promise[A],
onOk func(A) Promise[B],
onError func(error) Promise[B],
) Promise[B] {
var (
onOkJs js.Func
onErrorJs js.Func
)
onOkJs = js.FuncOf(func(this js.Value, args []js.Value) any {
defer onOkJs.Release()
return onOk(A(jsapi.Value{args[0]})).Value
})
if onError == nil {
return Promise[B]{
Value: pa.Value.Call("then", onOkJs),
}
}
onErrorJs = js.FuncOf(func(this js.Value, args []js.Value) any {
defer onErrorJs.Release()
return onError(jsapi.Error{Value: args[0]}).Value
})
return Promise[B]{
Value: pa.Value.Call("then", onOkJs, onErrorJs),
}
}
// Wait blocks on the promise, returning the value and any error when it resolves.
func (p Promise[T]) Wait() (T, error) {
return p.Thunk().Force().Get()
}
func (p Promise[T]) Thunk() *thunk.Thunk[orerr.OrErr[T]] {
result, fulfill := thunk.Promise[orerr.OrErr[T]]()
Then(
p,
func(v T) Promise[jsapi.Value] {
fulfill(orerr.New(v, nil))
return Resolve(jsapi.Value{})
},
func(err error) Promise[jsapi.Value] {
fulfill(orerr.New(T{}, err))
return Resolve(jsapi.Value{})
},
)
return result
}