@@ -19,28 +19,48 @@ package promise
19
19
import (
20
20
"context"
21
21
"fmt"
22
- "runtime/trace "
22
+ "reflect "
23
23
24
24
"fillmore-labs.com/promise/result"
25
25
)
26
26
27
- // List is a list of [Future], representing results of asynchronous tasks.
28
- type List [R any ] []Future [R ]
27
+ // AnyFuture matches a [Future] of any type.
28
+ type AnyFuture interface {
29
+ reflect () reflect.Value
30
+ }
31
+
32
+ // AwaitAll returns a function that yields the results of all futures.
33
+ // If the context is canceled, it returns an error for the remaining futures.
34
+ func AwaitAll [R any ](ctx context.Context , futures ... Future [R ]) func (yield func (int , result.Result [R ]) bool ) {
35
+ i := newIterator (ctx , convertValue [R ], futures )
29
36
30
- // All returns a function that yields the results of all futures.
37
+ return i .yieldTo
38
+ }
39
+
40
+ // AwaitAllAny returns a function that yields the results of all futures.
31
41
// If the context is canceled, it returns an error for the remaining futures.
32
- func (l List [R ]) All (ctx context.Context ) func (yield func (int , result.Result [R ]) bool ) {
33
- defer trace .StartRegion (ctx , "asyncSeq" ).End ()
34
- s := newIterator (ctx , l )
42
+ func AwaitAllAny (ctx context.Context , futures ... AnyFuture ) func (yield func (int , result.Result [any ]) bool ) {
43
+ i := newIterator (ctx , convertValueAny , futures )
44
+
45
+ return i .yieldTo
46
+ }
35
47
36
- return s .yieldTo
48
+ // AwaitAllResults waits for all futures to complete and returns the results.
49
+ // If the context is canceled, it returns early with errors for the remaining futures.
50
+ func AwaitAllResults [R any ](ctx context.Context , futures ... Future [R ]) []result.Result [R ] {
51
+ return awaitAllResults (len (futures ), AwaitAll (ctx , futures ... ))
37
52
}
38
53
39
- // AwaitAll waits for all futures to complete and returns the results.
54
+ // AwaitAllResultsAny waits for all futures to complete and returns the results.
40
55
// If the context is canceled, it returns early with errors for the remaining futures.
41
- func (l List [R ]) AwaitAll (ctx context.Context ) []result.Result [R ] {
42
- results := make ([]result.Result [R ], len (l ))
43
- l .All (ctx )(func (i int , r result.Result [R ]) bool {
56
+ func AwaitAllResultsAny (ctx context.Context , futures ... AnyFuture ) []result.Result [any ] {
57
+ return awaitAllResults (len (futures ), AwaitAllAny (ctx , futures ... ))
58
+ }
59
+
60
+ func awaitAllResults [R any ](n int , iter func (yield func (int , result.Result [R ]) bool )) []result.Result [R ] {
61
+ results := make ([]result.Result [R ], n )
62
+
63
+ iter (func (i int , r result.Result [R ]) bool {
44
64
results [i ] = r
45
65
46
66
return true
@@ -51,10 +71,21 @@ func (l List[R]) AwaitAll(ctx context.Context) []result.Result[R] {
51
71
52
72
// AwaitAllValues returns the values of completed futures.
53
73
// If any future fails or the context is canceled, it returns early with an error.
54
- func (l List [R ]) AwaitAllValues (ctx context.Context ) ([]R , error ) {
55
- results := make ([]R , len (l ))
74
+ func AwaitAllValues [R any ](ctx context.Context , futures ... Future [R ]) ([]R , error ) {
75
+ return awaitAllValues (len (futures ), AwaitAll (ctx , futures ... ))
76
+ }
77
+
78
+ // AwaitAllValuesAny returns the values of completed futures.
79
+ // If any future fails or the context is canceled, it returns early with an error.
80
+ func AwaitAllValuesAny (ctx context.Context , futures ... AnyFuture ) ([]any , error ) {
81
+ return awaitAllValues (len (futures ), AwaitAllAny (ctx , futures ... ))
82
+ }
83
+
84
+ func awaitAllValues [R any ](n int , iter func (yield func (int , result.Result [R ]) bool )) ([]R , error ) {
85
+ results := make ([]R , n )
56
86
var yieldErr error
57
- l .All (ctx )(func (i int , r result.Result [R ]) bool {
87
+
88
+ iter (func (i int , r result.Result [R ]) bool {
58
89
if r .Err () != nil {
59
90
yieldErr = fmt .Errorf ("list AwaitAllValues result %d: %w" , i , r .Err ())
60
91
@@ -70,13 +101,25 @@ func (l List[R]) AwaitAllValues(ctx context.Context) ([]R, error) {
70
101
71
102
// AwaitFirst returns the result of the first completed future.
72
103
// If the context is canceled, it returns early with an error.
73
- func (l List [R ]) AwaitFirst (ctx context.Context ) (R , error ) {
104
+ func AwaitFirst [R any ](ctx context.Context , futures ... Future [R ]) (R , error ) {
105
+ return awaitFirst (AwaitAll (ctx , futures ... ))
106
+ }
107
+
108
+ // AwaitFirstAny returns the result of the first completed future.
109
+ // If the context is canceled, it returns early with an error.
110
+ func AwaitFirstAny (ctx context.Context , futures ... AnyFuture ) (any , error ) {
111
+ return awaitFirst (AwaitAllAny (ctx , futures ... ))
112
+ }
113
+
114
+ func awaitFirst [R any ](iter func (yield func (int , result.Result [R ]) bool )) (R , error ) {
74
115
var v result.Result [R ]
75
- l .All (ctx )(func (_ int , r result.Result [R ]) bool {
116
+
117
+ iter (func (_ int , r result.Result [R ]) bool {
76
118
v = r
77
119
78
120
return false
79
121
})
122
+
80
123
if v == nil {
81
124
return * new (R ), ErrNoResult
82
125
}
0 commit comments