callback-timeout-flexible
Version:
Start with a short time limit and extend it dynamically. [npm search keywords: callback chain extend extendable extendible extensible flexible function prolong prolongable renew renewable time limit timeout]
136 lines (85 loc) • 3.97 kB
Markdown
<!--#echo json="package.json" key="name" underline="=" -->
callback-timeout-flexible
=========================
<!--/#echo -->
<!--#echo json="package.json" key="description" -->
Start with a short time limit and extend it dynamically.
<!--/#echo -->
Can be used to recover from broken callback chains that stop unexpectedly.
Start with a very short timeout, so you're notified when your function just
forgets to call back. The short limit won't be a problem for functions aware
of it, because they can dynamically extend/renew it.
Additional features:
* Helps you determine which function timed out.
API
---
This module exports one function:
### callbackTimeoutFlexible(origCb, timeoutSec)
Immediately starts a timeout timer, then returns a timeout-aware
callback (proxy) function `prx`.
When `prx` is called within `timeoutSec` seconds, it schedules
function `origCb` to be called very soon, with the same arguments
that were passed to `prx`. (`this` context is not preserved.)
When the timeout expires before `prx` is invoked, `origCb` will be called
with one argument, an `Error` that describes which timeout has expired.
(Or whatever `opt.errFac` returned, see below.)
The default error factory uses `'TimeoutError'` as the error's `.name`.
There's a timeout control object (TCO) in `prx.timeout`
which allows to extend the timeout (see below).
`timeoutSec` can be a config object instead of a number, with these options:
Mandatory options:
* `limitSec`: Timeout in seconds. Expected to be a positive number.
Optional options:
* `name`: A custom name for this timeout, to be used in or as its description.
* `onLateCall`: What to do when `prx` is called after `origCb` has
already been notified, either because of a previous `prx` invocation,
or because the timeout has expired.
* any `false`-y value: Don't notify. Discard the arguments.
* `true`: Forward the invocation to `origCb`.
* any function: Forward the invocation to that function.
* `onBeforeTimeout`: A function to be called (with one argument: the TCO)
just before `origCb` would be called with a timeout error.
It's intended as a last-minute opportunity to extend the timeout.
* `startTime`: Set to `true` to request timestamps.
* `errFac`: Factory function to use for producing the timeout errors.
* `errMsg`: Template string for the default error factory's error messages.
Supports these variable slots:
* `\v{name}`: `tco.name`
* `\v{this}`: `String(tco)`
* `autostart`: If set to `false`, timers won't be started immediately.
* `unref`: Set to `true` if timers shall be `.unref()`ed.
* The Node.js v8.11.3 API docs have an obscure performance warning about
`unref()`ed timers. Check your node version's docs if you care.
Timeout control objects
-----------------------
### .renew(sec)
* With a positive number as `sec`: Extend the timeout so it triggers
in `sec` seconds from now.
* `sec === true`: Extend timeout to now + the default timespan,
which usually is the `timeoutSec` with which `prx` was created.
* `sec === null`: Just discard the timeout timer.
### .abandon()
Shorthand for `.renew(null)`.
### Info and Stats
Treat these as read-only.
* `.hasTimedOut`: (boolean) Whether the timeout has expired.
* `.hadLateCalls`: `false` = `origCb` has not been notified yet;
non-negative integer: late call counter.
* `.startTime`: If timestamps were requested, creation time of the TCO.
* `.finishTime`: If timestamps were requested, this starts as `false`,
until the first call to `prx`, which then stores its current time here.
### Config options
These should be safe to modify after `prx` was created:
* `.limitSec`: __Has no effect__ on currently active timers but
changes the the default timespan for follow-up `.renew`als.
* `.onLateCall`
* `.errFac`
Usage
-----
see [usage.js](usage.js).
<!--#toc stop="scan" -->
License
-------
<!--#echo json="package.json" key=".license" -->
ISC
<!--/#echo -->