diff --git a/api.go b/api.go index 3c51796..7f0d58c 100644 --- a/api.go +++ b/api.go @@ -1,6 +1,7 @@ package future import ( + "context" "errors" "fmt" "runtime/debug" @@ -27,6 +28,22 @@ func Async[T any](f func() (T, error)) *Future[T] { return &Future[T]{state: s} } +func CtxAsync[T any](ctx context.Context, f func(ctx context.Context) (T, error)) *Future[T] { + s := &state[T]{} + go func() { + var val T + var err error + defer func() { + if r := recover(); r != nil { + err = fmt.Errorf("%w, err=%s, stack=%s", ErrPanic, r, debug.Stack()) + } + s.set(val, err) + }() + val, err = f(ctx) + }() + return &Future[T]{state: s} +} + func Lazy[T any](f func() (T, error)) *Future[T] { s := &state[T]{} s.state |= flagLazy diff --git a/api_test.go b/api_test.go index 896a655..e7d7312 100644 --- a/api_test.go +++ b/api_test.go @@ -1,6 +1,7 @@ package future import ( + "context" "math/rand" "runtime" "strconv" @@ -21,6 +22,16 @@ func TestAsync(t *testing.T) { assert.Equal(t, nil, err) } +func TestCtxAsync(t *testing.T) { + ctx := context.WithValue(context.Background(), "foo", "bar") + f := CtxAsync(ctx, func(ctx context.Context) (any, error) { + return ctx.Value("foo"), nil + }) + val, err := f.Get() + assert.Equal(t, "bar", val) + assert.Equal(t, nil, err) +} + func TestAsyncPanic(t *testing.T) { f := Async(func() (int, error) { panic("panic")