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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi.
Please while having a
*Promiseexposed out of ajsruntime environment into golang one in case ofPromiseStatePendingwhat 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
NewPromiseDo I see it right that
runtime.RunStringand all the similar handles its own event loop under the hood. And onceruntime.RunStringexecution is ended (returned a value) whether underling event loop still keep on further processing?Thnx
Beta Was this translation helpful? Give feedback.
All reactions