Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a promises package with a New helper function #3176

Merged
merged 7 commits into from
Jul 10, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions js/promises/promises.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Package promises provides helpers for working with promises in k6.
package promises

import (
"github.com/dop251/goja"
"go.k6.io/k6/js/modules"
)

// MakeHandledPromise can be used to create promises that will be dispatched to k6's event loop.
//
// Calling the function will create a goja promise and return its `resolve` and `reject` callbacks, wrapped
// in such a way that it will block the k6 JS runtime's event loop from exiting before they are
oleiade marked this conversation as resolved.
Show resolved Hide resolved
// called, even if the promise isn't revoled by the time the current script ends executing.
oleiade marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current documentation:

  1. does not explain why you would use that instead of goja.NewRuntime()
  2. Explains things that arguably are better left explain in the eventloop package - and they are.

I would propose that we do actually document why you will want to use this and simple say it uses the underlying eventloop mechanism.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point 👍🏻 Will adapt it indeed 🚀

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an attempt at improving the documentation accordingly:

// MakeHandledPromise facilitates the creation of promises within k6 modules.
//
// Whenever a k6 module function or methods returns a promise, it very likely
// should be created using this function as it ensures the promise is correctly
// managed by k6's event loop.
//
// The function returns a promise, a resolve function and a reject function. The
// promise is the one that should be returned by the function, and the `resolve`
// and `reject` functions should be used to resolve or reject the promise.
//
// Usage example:
//
//	   func myAsynchronousFunction(vu modules.VU) *goja.Promise {
//		    promise, resolve, reject := CreateAsyncFunctionPromise(vu)
//		    go func() {
//		        value, err := someAsynchronousOperation()
//				   if err != nil {
//		            reject(err)
//		            return
//		        }
//
//		        resolve(value)
//		    }()
//		    return promise
//		  }
//
// In the above example, `someAsynchronousOperation` represents an operation that might take a while to finish,
// and k6 script execution shouldn't be halted during its execution. This function ensures such an operation
// is correctly managed within k6's event loop.

WDYT? Suggestions to improve?

//
// A typical usage would be:
//
// func myAsynchronousFunc(vu modules.VU) *(goja.Promise) {
// promise, resolve, reject := promises.MakeHandledPromise(vu)
// go func() {
// v, err := someAsyncFunc()
// if err != nil {
// reject(err)
// return
// }
//
// resolve(v)
// }()
// return promise
// }
func MakeHandledPromise(vu modules.VU) (*goja.Promise, func(interface{}), func(interface{})) {
oleiade marked this conversation as resolved.
Show resolved Hide resolved
runtime := vu.Runtime()
callback := vu.RegisterCallback()
promise, resolve, reject := runtime.NewPromise()
oleiade marked this conversation as resolved.
Show resolved Hide resolved

return promise, func(i interface{}) {
callback(func() error {
resolve(i)
return nil
})
}, func(i interface{}) {
callback(func() error {
reject(i)
return nil
})
}
}