Wrap a function so this job will be active when it's called.
The function to wrap
A function with the same signature(s), but will have this job active when called. (Note: signal dependency tracking will be disabled for the duration of the call, as if it had been wrapped with peek().)
Note that if the supplied function has any custom properties, they will not be available on the returned function at runtime, even though TypeScript will act as if they are present at compile time. This is because the only way to copy all overloads of a function signature is to copy the exact type (as TypeScript has no way to generically say, "this is a function with all the same overloads, but none of the properties").
Start a nested job that will end when the given stream does
This is basically shorthand for start<void>(job => void src(sink, job, inlet))
-- i.e. a quick way to subscribe to a finite and/or pausable stream.
A job that can be aborted to end the subscription, and which will end naturally (with a void return or error) if the stream ends itself.
Readonly
endRelease all resources held by the job.
Arrange for all cleanup functions and result consumers added to the job (via release, must, do, etc.) be called in the appropriate order. When the call to end() returns, all child jobs will have been notified of their cancellation. (But not all of their cleanups or result consumers may have run yet, in the event that another job's end() is in progress when this method is called.)
If any callbacks throw exceptions, they're converted to unhandled promise rejections (so that all of them will be called, even if one throws an error).
Note: this method is a bound function, so you can pass it as a callback to another job, event source, etc.
Restart this job - works just like .end(), except that the job isn't ended, so cleanup callbacks can be added again and won't be invoked until the next restart or the job is ended. Note that the job's startup code will not be rerun: this just runs an early cleanup and then "uncancels" the job, changing its result() from CancelResult back to undefined. It's up to you to do any needed re-initialization.
Unlinke .end(), restart() guarantees that all cleanups and result consumers for the target job will have completed running when it returns.
The restarting wrapper can be used to make a function that runs over and over in the same job, restarting each time.
Invoke a function with this job as the active one, so that calling the global must function will add cleanup callbacks to it, start will create child jobs of it, etc. (Note: signal dependency tracking is disabled for the duration of the call, as if it had been wrapped with peek().)
The result of calling fn(...args)
Start a nested job using the given function (or Yielding, promise, etc.). (Like start(), but using a specific job as the parent, rather than whatever job is active. Zero, one, and two arguments are supported, just as with start().)
Set up a callback to receive unhandled errors from child jobs.
Setting an async-catch handler allows you to create robust parent jobs that log or report errors and restart either a single job or an entire group of them, in the event that a child job malfunctions in a way that's not caught elsewhere.
Either an error-receiving callback, or null. If null,
asyncThrow()n errors for the job will be passed to the job's throw()
method instead. If a callback is given, it's called with this
bound to
the relevant job instance.
Informs a job of an unhandled error from one of its children.
If the job has an .asyncCatch() handler set, it will be called with the error, otherwise the job will end with the supplied error. If the error then isn't handled by a listener on the job, the error will cascade to an asyncThrow on the job's parent, until the detached job and its asyncCatch handler is reached. (Which defaults to creating an unhandled promise rejection.)
Note: application code should not normally need to call this method directly, as it's automatically invoked on a job's parent if the job fails with no error listeners. (That is, if a job result isn't awaited by anything and has no onError handlers, and the job throws, then the error is automatically asyncThrow()n to the job's parent.)
The error thrown by the child job
An iterator suitable for use with yield *
(in a job generator) to
obtain a result.
Invoke a callback with the result of a job. Similar to
Job.must(), except that do
callbacks run in FIFO order after
all Job.must() and Job.release() callbacks are done for
the same job.
These callbacks are used internally to implement promises, and should generally be used when you want to perform actions based on the result of a job. (Whereas Job.must() callbacks are intended to clean up resources used by the job itself, and Job.release() callbacks are used to notify other activities (such as child jobs) that they are being canceled.)
Invoke a callback if the job ends with an cancellation or .restart().
This is shorthand for a .do() callback that checks for an error and marks it handled, so it uses the same relative order and runs in the same group as other .do callbacks.
A callback that will receive the error
Invoke a callback if the job ends with an error.
This is shorthand for a .do() callback that checks for an error and marks it handled, so it uses the same relative order and runs in the same group as other .do callbacks.
A callback that will receive the error
End the job with a return value, passing a ValueResult to the cleanup callbacks. (Throws an error if the job is already ended or is currently restarting.) Provides the same execution and ordering guarantees as .end().
End the job with a thrown error, passing an ErrorResult to the cleanup callbacks. (Throws an error if the job is already ended or is currently restarting.) Provides the same execution and ordering guarantees as .end().
Note: since this immediately ends the job with an error, it should only be called by the job when it is no longer able to continue. If you want to notify a job about an error in a different job, you may want to use .asyncThrow() instead.
Add a cleanup callback to be run when the job is ended or restarted. (Non-function values are ignored.) If the job has already ended, the callback will be invoked asynchronously in the next microtask. Cleanup functions are run in LIFO order, after any Job.release() callbacks (including those of the job's children), but before any Job.do() callbacks are run for the same job.
Generally speaking, this method is used within a job to arrange for used resources to be cleaned up or to undo other state that was only supposed to be active while the job was running.
Optional
cleanup: OptionalCleanup<unknown>Create a mutual-cleanup link with a resource that might be stopped or terminated in some way before the job ends. (Like a child process, a server connection, etc.)
If a job uses a lot of such resources, using Job.must callbacks to trigger each one would result in an ever growing number of callbacks (and uncollectable reference to the no-longer-usable resources). So this method lets you remove a cleanup function when it's no longer needed: when the resource is closed or finished, invoking the callback returned by this method will remove the cleanup callback from the job, allowing the resource to be freed before the job ends, without accumulating an endless number of callbacks in the job. (Uneventful also uses this mechanism internally to link child jobs to their parents.)
In order to ensure that all such "child" jobs, resources, and activities are marked as canceled before any side effects (such as events, callbacks or I/O operations) can occur, Uneventful prioritizes all release callbacks to run before any other callbacks of any kind. Since release callbacks are used for child jobs, this means that the entire job subtree is notified immediately of cancellation, before any other actions are taken. This ensures that no "stray" operations can continue, unaware that their job is canceled.
This means, however, that release callbacks must do only simple actions that can't result in arbitrary code being synchronously run. (Some safe examples would be setting flags, cancelling event subscriptions, removing things from internal queues, etc.) Synchronously triggering events or other callbacks, however, runs the risk of that code doing things it wouldn't have done if it knew its job were canceled.
Note that if you still need such actions to happen, your release callback can always add a new Job.must() or Job.do() callback at that point, and the callback will then get done during a later phase of job cleanup, without losing the benefits of the mutual-cleanup process.
A callback that should be used to remove the passed-in cleanup callback from the job, if the resource is disposed of before the job ends.
Readonly
[toAttaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The resolved value cannot be modified from the callback.
Optional
onfinally: (() => void)The callback to execute when the Promise is settled (fulfilled or rejected).
A Promise for the completion of the callback.
Attaches callbacks for the resolution and/or rejection of the Promise.
A Promise for the completion of which ever callback is executed.
A cancellable asynchronous operation with automatic resource cleanup.
You can add cleanup callbacks to a job via must() or its .must() method. When the job is ended or canceled, the callbacks are (synchronously) run in reverse order -- a bit like a delayed and distributed collection of
finally
blocks.Jobs implement the Promise interface (then, catch, and finally) so they can be passed to Promise-using APIs or awaited by async functions. They also implement Yielding, so you can await their results from a start() using
yield *
. They also have .return() and .throw() methods so you can end a job with a result or error.Most jobs, however, are not intended to produce results, and are merely canceled (using .end() or .restart()).
Jobs can be created using start(), detached.start(), and makeJob().