Subscribe *Promise Pending Status #601
Replies: 4 comments
-
P.S. I mean whether it is possible to subscribe to a state change purely on a
|
Beta Was this translation helpful? Give feedback.
-
I was wondering the same thing. Would it be possible to expose the promise job queue? Ideally it could be driven with: https://github.com/dop251/goja_nodejs/blob/master/eventloop/eventloop.go, but you could make your own event loop. |
Beta Was this translation helpful? Give feedback.
-
I understand that Right now I'm doing this hack: func watchPromise(promise *goja.Promise, interval time.Duration) <-chan struct{} {
doneChan := make(chan struct{})
go func() {
defer close(doneChan)
for {
// I'm assuming this particular call is goroutine-safe, as it's only a `return p.state`
// under the hood, and `state` is effectively an `int` that can change only once.
state := promise.State()
if state != goja.PromiseStatePending {
break
}
time.Sleep(interval)
}
}()
return doneChan
} I hope my assumption there is correct - please let me know if it's not. However, I don't like my code as it requires an extra goroutine for each Obviously, accessing jsCode := `async function run() { return 2+2; }`
loop := eventloop.NewEventLoop()
// Set things up, call run() and obtain the promise
var runPromise *goja.Promise
loop.RunOnLoop(func(vm *goja.Runtime) {
_, err := vm.RunString(jsCode)
if err != nil {
runPromise = newRejectedPromise(vm, err)
return
}
if runFunc, ok := goja.AssertFunction(vm.Get("run")); ok {
promiseValue, err := runFunc(goja.Undefined())
if err == nil {
if p, ok := promiseValue.Export().(*goja.Promise); ok {
runPromise = p
return
}
}
}
runPromise = newRejectedPromise(vm, "something went wrong")
})
loop.Start()
// Wait until we got the promise
for runPromise == nil { // I'm just being lazy here, there are better ways to do this
time.Sleep(100 * time.Millisecond)
}
// Wait until the promise is resolved, then schedule code to do something about it
<-watchPromise(runPromise, 100*time.Millisecond)
loop.RunOnLoop(func(vm *goja.Runtime) {
switch runPromise.State() {
case goja.PromiseStateFulfilled:
fmt.Println("Promise resolved with result:", runPromise.Result())
case goja.PromiseStateRejected:
fmt.Println("Promise was rejected:", runPromise.Result())
}
}) If this is a viable approach, how about introducing something like Thanks a lot! |
Beta Was this translation helpful? Give feedback.
-
Here is my solution. It works nicely. I just wish I could inject my own import "github.com/dop251/goja_nodejs/eventloop"
func await(promise *goja.Promise) (string, error) {
done := make(chan struct{})
go func() {
defer close(done)
for promise.State() == goja.PromiseStatePending {
time.Sleep(50 * time.Millisecond)
}
return
}()
<-done
switch promise.State() {
case goja.PromiseStateFulfilled:
return promise.Result().Export().(string), nil
default: // case goja.PromiseStateRejected:
return "", errors.New(promise.Result().Export().(string))
}
}
func Preprocess(ctx context.Context, source string, preprocessor []PreprocessorGroup) (*Processed, error) {
if ctx == nil {
ctx = context.Background()
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
loop := eventloop.NewEventLoop()
res := make(chan *goja.Promise)
defer close(res)
loop.RunOnLoop(func(vm *goja.Runtime) {
_, err := vm.RunProgram(prog)
if err != nil {
panic(err)
}
v, err := vm.RunString(fmt.Sprintf(`preprocess(`+"`%s`)", source))
if err != nil {
panic(err)
}
res <- v.Export().(*goja.Promise)
})
loop.Start()
defer loop.Stop()
p, err := await(<-res)
if err != nil {
return nil, err
}
processed := &Processed{}
panic(p)
err = json.Unmarshal(unsafeBytes(p), processed)
if err != nil {
panic(err)
}
return processed, nil
} |
Beta Was this translation helpful? Give feedback.
-
Hi.
Please while having a
*Promise
exposed out of ajs
runtime environment into golang one in case ofPromiseStatePending
what would be the best option to wait/subscribe for event once it is naturally resolved/rejected within the initial runtime? (Except of just a periodical state check)E.g.
For the very same reason please clarify from the docs of
NewPromise
Do I see it right that
runtime.RunString
and all the similar handles its own event loop under the hood. And onceruntime.RunString
execution is ended (returned a value) whether underling event loop still keep on further processing?Thnx
Beta Was this translation helpful? Give feedback.
All reactions