The Promises package provides an implementation of promises similar to JavaScript Promise for Go.
This is a cleaner alternative to using channels, wait groups and goroutines for asynchronous operations.
With this, you can write asynchronous code that looks like synchronous code.
This is also compatible with the context package, so you can use them with context.Context.
And this is written as go-way
.
Import the promises
package in your Go code to use it:
import "github.com/oneofthezombies/promises"
You can create promises using the New function, passing an executor function that defines the asynchronous operation and how it should be resolved or rejected.
Here's a basic example:
// promises_test.go
func TestAwait(t *testing.T) {
ctx := context.Background()
p := New(func(resolve Resolve[int], reject Reject) {
resolve(1)
})
v, err := p.Await(ctx)
if err != nil {
t.Errorf("expected error to be nil, got %v", err)
}
if v != 1 {
t.Errorf("expected value to be 1, got %d", v)
}
}
Done: Get a channel that is closed when the promise is settled.
Value: Get the value that the promise was fulfilled with.
Reason (or Err for compatibility): Get the reason that the promise was rejected.
IsFulfilled, IsRejected, IsSettled: Check the state of the promise.
You can use the All method to wait for multiple promises to be settled:
// promises_test.go
func TestAllWithLoop(t *testing.T) {
ctx := context.Background()
var promises []*Promise[int]
for i := 0; i < 100; i++ {
i := i // https://golang.org/doc/faq#closures_and_goroutines
p := New(func(resolve Resolve[int], reject Reject) {
resolve(i)
})
promises = append(promises, p)
}
p := All(ctx, promises...)
v, err := p.Await(ctx)
if err != nil {
t.Errorf("expected error to be nil, got %v", err)
}
if len(v) != 100 {
t.Errorf("expected length to be 100, got %d", len(v))
}
for i, value := range v {
if value != i {
t.Errorf("expected value to be %d, got %d", i, value)
}
}
}
You can use the AllSettled method to wait for multiple promises to be settled, regardless of whether they are resolved or rejected:
// promises_test.go
func TestAllSettledWithLoop(t *testing.T) {
ctx := context.Background()
var promises []*Promise[int]
for i := 0; i < 100; i++ {
i := i // https://golang.org/doc/faq#closures_and_goroutines
p := New(func(resolve Resolve[int], reject Reject) {
resolve(i)
})
promises = append(promises, p)
}
p := AllSettled(ctx, promises...)
v, err := p.Await(ctx)
if err != nil {
t.Errorf("expected error to be nil, got %v", err)
}
if len(v) != 100 {
t.Errorf("expected length to be 100, got %d", len(v))
}
for i, result := range v {
if result.Status != Fulfilled {
t.Errorf("expected status to be Fulfilled, got %v", result.Status)
}
if result.Value != i {
t.Errorf("expected value to be %d, got %d", i, result.Value)
}
}
}
If you would like to contribute to this project, please follow these steps:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Make your changes and ensure they pass the existing tests.
- Add new tests if necessary.
- Commit your changes with clear commit messages.
- Push your branch to your fork.
- Create a pull request to the original repository.
This package is licensed under the MIT License. See the LICENSE file for details.