A FlowExecutor has await(): RT to enable the parent flow to await its result.

Here’s an example:

class Main {
	hello() {
		const flow = std.flow<Main>("Print!", this).world("Hello");
		this.print(flow);
	}

	world(arg: string) {
		return `${arg} World!`;
	}

	print(flow: std.FlowExecutor<string, Main['world']>) {
		const result = flow.await(); // We can 'await' a flow and get its result.
		std.log(result);
	}
}

The line const result = flow.await(); will make the currently executing flow suspend until the awaited flow is complete.

This is similar to async/await features that exist in other languages.

If you await a flow, it will count as calling that method(FlowFunction) and hence an edge would be rendered.

Try playing with run() and await() and see how the playground changes!

Awaiting multiple flows

In real systems, you are often awaiting multiple things simultaneously, or racing them together. That’s exactly why we have std.awaitAll() and std.awaitRace().

std.awaitAll

This is the equivalent of JavaScript’s Promise.all. It takes an array of FlowExecutor and returns an array corresponding to results of given FlowExecutors. For example:

const result = std.awaitAll([
	flow1,
	flow2,
	flow3,
]);

std.log(result);
// Assuming all the flows returned 42. The above statement would log [42,42,42]

std.awaitRace

This is the equivalent of JavaScript’s Promise.race. It also takes an array of FlowExecutor but returns a single value corresponding to the flow which completed first. If a flow wins the race, the remaining flows are cancelled. For example:

const result = std.awaitRace([
	flow1,
	flow2,
	flow3,
]);

std.log(result);
// Assuming all the flows return 42, and flow3 completed first.
// The above statement would log 42

Here’s how it looks like in action:

You can play with the code here.


We have one last mechanism left, events. The tried and tested method for asynchronousity. Let’s cover that in next section!