123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- # tryer
- [](https://gitlab.com/philbooth/tryer/pipelines)
- [](https://www.npmjs.com/package/tryer)
- [](https://www.npmjs.com/package/tryer)
- [](https://opensource.org/licenses/MIT)
- Because everyone loves a tryer!
- Conditional
- and repeated
- function invocation
- for node
- and browser.
- * [Say what?](#say-what)
- * [What size is it?](#what-size-is-it)
- * [How do I install it?](#how-do-i-install-it)
- * [How do I use it?](#how-do-i-use-it)
- * [Loading the library](#loading-the-library)
- * [Calling the exported function](#calling-the-exported-function)
- * [Examples](#examples)
- * [How do I set up the dev environment?](#how-do-i-set-up-the-dev-environment)
- * [What license is it released under?](#what-license-is-it-released-under)
- ## Say what?
- Sometimes,
- you want to defer
- calling a function
- until a certain
- pre-requisite condition is met.
- Other times,
- you want to
- call a function
- repeatedly
- until some post-requisite condition
- is satisfied.
- Occasionally,
- you might even want
- to do both
- for the same function.
- To save you writing
- explicit conditions
- and loops
- on each of those occasions,
- `tryer` implements
- a predicate-based approach
- that hides the cruft
- behind a simple,
- functional interface.
- Additionally,
- it allows you to easily specify
- retry intervals
- and limits,
- so that your code
- doesn't hog the CPU.
- It also supports
- exponential backoff
- of retry intervals,
- which can be useful
- when handling
- indefinite error states
- such as network failure.
- ## What size is it?
- 5.6 kb unminified with comments, 1.1 kb minified, 0.5 kb minified + gzipped.
- ## How do I install it?
- Via npm:
- ```
- npm i tryer --save
- ```
- Or if you just want the git repo:
- ```
- git clone git@gitlab.com:philbooth/tryer.git
- ```
- ## How do I use it?
- ### Loading the library
- If you are running in
- Node.js
- or another CommonJS-style
- environment,
- you can `require`
- tryer like so:
- ```javascript
- const tryer = require('tryer');
- ```
- It also the supports
- the AMD-style format
- preferred by Require.js.
- If you are
- including `tryer`
- with an HTML `<script>` tag,
- or neither of the above environments
- are detected,
- it will be exported globally as `tryer`.
- ### Calling the exported function
- `tryer` is a function
- that can be invoked to
- call other functions
- conditionally and repeatedly,
- without the need for
- explicit `if` statements
- or loops in your own code.
- `tryer` takes one argument,
- an options object
- that supports
- the following properties:
- * `action`:
- The function that you want to invoke.
- If `action` returns a promise,
- iterations will not end
- until the promise is resolved or rejected.
- Alternatively,
- `action` may take a callback argument, `done`,
- to signal that it is asynchronous.
- In that case,
- you are responsible
- for calling `done`
- when the action is finished.
- If `action` is not set,
- it defaults to an empty function.
- * `when`:
- A predicate
- that tests the pre-condition
- for invoking `action`.
- Until `when` returns true
- (or a truthy value),
- `action` will not be called.
- Defaults to
- a function that immediately returns `true`.
- * `until`:
- A predicate
- that tests the post-condition
- for invoking `action`.
- After `until` returns true
- (or a truthy value),
- `action` will no longer be called.
- Defaults to
- a function that immediately returns `true`.
- * `fail`:
- The error handler.
- A function
- that will be called
- if `limit` falsey values
- are returned by `when` or `until`.
- Defaults to an empty function.
- * `pass`:
- Success handler.
- A function
- that will be called
- after `until` has returned truthily.
- Defaults to an empty function.
- * `limit`:
- Failure limit,
- representing the maximum number
- of falsey returns from `when` or `until`
- that will be permitted
- before invocation is deemed to have failed.
- A negative number
- indicates that the attempt
- should never fail,
- instead continuing
- for as long as `when` and `until`
- have returned truthy values.
- Defaults to `-1`.
- * `interval`:
- The retry interval,
- in milliseconds.
- A negative number indicates
- that each subsequent retry
- should wait for twice the interval
- from the preceding iteration
- (i.e. exponential backoff).
- The default value is `-1000`,
- signifying that
- the initial retry interval
- should be one second
- and that each subsequent attempt
- should wait for double the length
- of the previous interval.
- ### Examples
- ```javascript
- // Attempt to insert a database record, waiting until `db.isConnected`
- // before doing so. The retry interval is 1 second on each iteration
- // and the call will fail after 10 attempts.
- tryer({
- action: () => db.insert(record),
- when: () => db.isConnected,
- interval: 1000,
- limit: 10,
- fail () {
- log.error('No database connection, terminating.');
- process.exit(1);
- }
- });
- ```
- ```javascript
- // Attempt to send an email message, optionally retrying with
- // exponential backoff starting at 1 second. Continue to make
- // attempts indefinitely until the call succeeds.
- let sent = false;
- tryer({
- action (done) {
- smtp.send(email, error => {
- if (! error) {
- sent = true;
- }
- done();
- });
- },
- until: () => sent,
- interval: -1000,
- limit: -1
- });
- ```
- ```javascript
- // Poll a device at 30-second intervals, continuing indefinitely.
- tryer({
- action: () => device.poll().then(response => handle(response)),
- interval: 30000,
- limit: -1
- });
- ```
- ## How do I set up the dev environment?
- The dev environment relies on
- [Chai],
- [JSHint],
- [Mocha],
- [please-release-me],
- [spooks.js] and
- [UglifyJS].
- The source code is in
- `src/tryer.js`
- and the unit tests are in
- `test/unit.js`.
- To install the dependencies:
- ```
- npm i
- ```
- To run the tests:
- ```
- npm t
- ```
- To lint the code:
- ```
- npm run lint
- ```
- To regenerate the minified lib:
- ```
- npm run minify
- ```
- ## What license is it released under?
- [MIT](COPYING)
- [chai]: http://chaijs.com/
- [jshint]: http://jshint.com/
- [mocha]: http://mochajs.org/
- [please-release-me]: https://gitlab.com/philbooth/please-release-me
- [spooks.js]: https://gitlab.com/philbooth/spooks.js
- [uglifyjs]: http://lisperator.net/uglifyjs/
- [license]: COPYING
|