rogchap / v8go

Execute JavaScript from Go

Home Page:https://rogchap.com/v8go

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to get value from async function all?

ppedziwiatr opened this issue · comments

Hey,

assuming this code:

func main() {
	iso := v8.NewIsolate()
	defer iso.Dispose()
	ctx := v8.NewContext(iso)
	defer ctx.Close()

	// TODO: load contract definition from Warp GW
	ctx.RunScript(`
	const handle = async function handle(state, action) {
	  if (action.input.function === "add") {
		state.counter++;
		return { state };
	  }
	}`, "contract.js")

	// TODO: load contract interactions from Warp GW
	ctx.RunScript(`
	let result = await handle({counter: 0}, {caller: 'ppe', input: {function: 'add'}})
	result = await handle(result.state, {caller: 'ppe', input: {function: 'add'}})
	result = await handle(result.state, {caller: 'ppe', input: {function: 'add'}})
`, "interactions.js")

	val, _ := ctx.RunScript("JSON.stringify(result)", "value.js")

	fmt.Printf("contract state: %s", val)
}

how to properly handle a promise and get a value from result?

Ofc. above example without async/await works flawlessly.

+1, I'm also stuck on this.

In Go you have to check if the result value from V8 is a promise; if it is, you check its state. As long as it's still in the unresolved state, you call the context's PerformMicrotaskCheckpoint method to run a bit longer, then recheck the promise state.

func resolvePromise(val *v8.Value, err error) (*v8.Value, error) {
	if err != nil || !val.IsPromise() {
		return val, err
	}
	for {
		switch p, _ := val.AsPromise(); p.State() {
		case v8.Fulfilled:
			return p.Result(), nil
		case v8.Rejected:
			return nil, errors.New(p.Result().DetailString())
		case v8.Pending:
			r.ctx.PerformMicrotaskCheckpoint() // run VM to make progress on the promise
			// go round the loop again...
		default:
			return nil, fmt.Errorf("illegal v8.Promise state %d", p) // unreachable
		}
	}
}