PromiseCapability and Then method for Value
I wanted a clean way to return/await promises without global state or parsing code.
I am wondering what your thoughts are on a Go-side queue that would execute tasks in ExecutePendingJobs.
In my prototype, I had something like this:
func (vm *VM) EventLoop() error {
for {
n, err := vm.ExecutePendingJobs()
if err != nil {
return fmt.Errorf("ExecutePendingJobs: %w", err)
}
if n > 0 {
continue
}
if vm.pending == 0 {
return nil
}
(<-vm.tasks)()
vm.pending--
}
}
func (vm *VM) schedule(fn func()) {
vm.tasks <- fn
}One pending task per Promise:
func (vm *VM) NewPromise() (*Promise, error) {
p, resolve, reject, err := NewPromise(vm.VM)
if err != nil {
return nil, err
}
vm.pending++
return &Promise{vm: vm, promise: p, resolve: resolve, reject: reject}, nil
}
func (p *Promise) Resolve(value any) {
p.vm.schedule(func() {
p.resolve.Call(quickjs.UndefinedValue, value)
p.Free()
})
}In order to solve this in a generic way, maybe we could generalize a Promise (or task) as a goroutine.
As long as there is a goroutine running, we would await more tasks, roughly:
vm.RegisterFunc("startAsync", func(args ...any) quickjs.Value {
vm.Go(func() {
time.Sleep(time.Millisecond * 200)
promise.Resolve("async result")
})
return promise
}, false)I'm looking forward to your take on it.
Next, I want to look at async generators.