dop251 / goja_nodejs

Nodejs compatibility library for Goja
MIT License
336 stars 81 forks source link

EventLoop : Wait for all jobs to finish #63

Closed bubbajoe closed 1 year ago

bubbajoe commented 1 year ago

Is it possible to add a function to the eventloop to allow for waiting for all jobs to finish.

dop251 commented 1 year ago

Have you tried the Run() method?

zyxkad commented 1 year ago

Have you tried the Run() method?

I think if you can provide a channel which will closed after the loop is done, it will be better

zyxkad commented 1 year ago

Have you tried the Run() method?

And Run() won't help in this case:


func (loop *EventLoop) setRunning() {
    loop.stopLock.Lock()
    defer loop.stopLock.Unlock()
    if loop.running {
        panic("Loop is already started")
    }
    loop.running = true
    atomic.StoreInt32(&loop.canRun, 1)
}

// Run calls the specified function, starts the event loop and waits until there are no more delayed jobs to run
// after which it stops the loop and returns.
// The instance of goja.Runtime that is passed to the function and any Values derived from it must not be used
// outside the function.
// Do NOT use this function while the loop is already running. Use RunOnLoop() instead.
// If the loop is already started it will panic.
func (loop *EventLoop) Run(fn func(*goja.Runtime)) {
    loop.setRunning()
    fn(loop.vm)
    loop.run(false)
}

It will panic if the loop is already start

zyxkad commented 1 year ago

Ok I think I got what you mean, you probably want us to start a new goroutine to use Run, and fire a signal after the run exited, it will work

bubbajoe commented 1 year ago

For my use case, I have an async function (that returns a promise), so once called and the promise is returned, i want to wait until the promise resolves, then check the state of the promise. Actually having a wait function in Promises would be more useful for me, but maybe it doesn't belong there.

Anyways, let me know if you have any ideas on how to solve this? Currently, im using a while loop, to check the state, until it resolves.

zyxkad commented 1 year ago

(deleted comment)

I'm sorry, didn't noticed you are asking goja, I'm working on wasm at the same time so mixed them up

zyxkad commented 1 year ago

For goja, you may call Promise.then as well, for example:

fn, _ := goja.AssertFunction(asyncFn)
res, err := fn(nil, args...)
if err != nil { ... }
promise := res.ToObject(vm)
assert(vm.InstanceOf(promise, vm.Get("Promise")))

done := make(chan goja.Value, 1)
errCh := make(chan goja.Value, 1)

then, _ := goja.AssertFunction(promise.Get("then"))
then(promise, vm.ToValue(func(call goja.FunctionCall)(goja.Value){
    done <- call.Arguments[0]
    return nil
}))
catch, _ := goja.AssertFunction(promise.Get("catch"))
catch(promise, vm.ToValue(func(call goja.FunctionCall)(goja.Value){
    errCh <- call.Arguments[0]
    return nil
}))

select{
case res := <-done:
case err := <-errCh:
  panic(err)
}

I didn't test it so I can't ensure it will work.