Core
Overview
This section will present a set of what I consider to be core operators e.g those that present a core functionality to work with channels and routines.
call<O extends (...a1: readonly any[]) => any, Params extends Parameters>(fn: O, ...args: Params): CallInstruction
This is the most basic operator and on a surface it just applies a function to whatever arguments you supply to it. If a function returns a generator, promise or an operator's result, it still will be handled properly by a generator runner. Its main purpose is to register a function call as an operation inside a generator so when using testGeneratorRunner
this call would show up and you would be able to test against it.
put<C extends Channel>(ch: C, data: FlattenChannel): Generator<Generator<undefined, void, unknown>, boolean, unknown>
Is a blocking operation. This operator will attempt to put a value to the channel. It will return true
if operation is successfull, or false
if operation is failed due to closed channel. It will throw an error if you try to put a null into the channel. Once the put operation is complete the generator resumes its execution. Put operation can be blocked if the channel's buffer is not able to receive new values, for example if the channel contains a fixed buffer and it is full. Has a promise variant which can be used outside of generators called putAsync.
take<C extends Channel>(ch: C): Generator<Generator<undefined, any, unknown>, any, FlattenChannel | null>
offer<C extends Channel>(ch: C, data: FlattenChannel): Generator<undefined, boolean | null, unknown>
Attempts to immediately insert a value into the channel. Returns either true
or false
. Returns false
if the channel is closed or the channel is not ready to accept an incoming put. Returns true
is operations succeeded.
poll<C extends Channel>(ch: C): Generator<undefined, any, unknown>
Attempts to immediately retrieve value from the channel. Returns null
if the channel is closed or channel has no values. Returns a value if an operation is successful.
fork<GenFn extends (...a1: readonly any[]) => Generator>(genFn: GenFn, ...args: Parameters): ForkInstruction
Is a non-blocking operation. Accepts a generator function and launches it as a forked child routine relative to the parent generator. Parent generator will not be done unless all forked routines are done executing. Cancelling parent generator will cause a recursive cancellation of forked routines. Errors from forked routines will propagate to the parent generator.
Cancelling forked routine
Inside a generator a value returned from yielding a fork operation is a cancellable promise which resolves once a forked generator is done. So you can just simply cancel this promise to cancel a forked generator by using .cancel
method.
Error propagation
If a forked routine throws an error while the parent routine is blocked, the error will be propagated into a try..catch
block inside a parent generator. Parent routine will be cancelled immediately if possible. In this case delay(1000)
started running before an error was thrown. And since we can't cancel a native promise, parent generator will wait for it to complete before cancelling itself. We can imagine a case when a generator call could be instead of our delay, and since we can indeed cancel a generator execution mid air, parent routine would terminate as soon as a generator running is cancelled.
If parent routine does not have a try..catch
block the whole parent routine will be rejected with an error and can be caught by using a .catch
method on cancellablePromise
returned by go
function.
spawn<GenFn extends (...a1: readonly any[]) => Generator>(genFn: GenFn, ...args: Parameters): SpawnInstruction
Is a non-blocking operation. Accepts a generator function to spawn. Spawned routines in comparison with forked ones will not propagate errors to parent routine. Spawned routines also will not be "waited" for by a parent routine once it completes. This operators also returns a cancellablePromise
which can be cancelled in a same manner as with forked routines.
Last updated