Select Git revision
promise.go 1.25 KiB
package jobqueue
import (
"sync"
)
type Promise[T any] struct {
isDone bool
value T
err error
mux sync.Mutex
done chan struct{}
resolve func(T)
reject func(error)
}
func NewPromise[T any](fn func(resolve func(T), reject func(error))) *Promise[T] {
p := &Promise[T]{
done: make(chan struct{}),
}
p.resolve = func(value T) {
p.mux.Lock()
defer p.mux.Unlock()
if p.isDone {
return
}
p.isDone = true
p.value = value
close(p.done)
}
p.reject = func(err error) {
p.mux.Lock()
defer p.mux.Unlock()
if p.isDone {
return
}
p.isDone = true
p.err = err
close(p.done)
}
go fn(p.resolve, p.reject)
return p
}
func Then[T, U any](p *Promise[T], onFulfilled func(T) (U, error), onRejected func(error) error) *Promise[U] {
return NewPromise[U](func(resolve func(U), reject func(error)) {
<-p.done
p.mux.Lock()
defer p.mux.Unlock()
if p.err != nil {
err := onRejected(p.err)
reject(err)
} else {
go func() {
res, err := onFulfilled(p.value)
if err != nil {
reject(err)
} else {
resolve(res)
}
}()
}
})
}
func Catch[T any](p *Promise[T], onRejected func(error) error) *Promise[T] {
return Then[T, T](p, func(value T) (T, error) {
return value, nil
}, onRejected)
}