{"_id":"understudy","_rev":"43-434daf1f66b60ec1398e6c02fb2fcee2","name":"understudy","description":"action interceptor for dynamic extensible systems","dist-tags":{"latest":"4.1.0"},"versions":{"0.0.1":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","version":"0.0.1","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@0.0.1","dist":{"shasum":"dc6c87d664cc7c900f6a8a3a43bba86d11eff64a","tarball":"https://registry.npmjs.org/understudy/-/understudy-0.0.1.tgz","integrity":"sha512-XDYyiXrLFdzxflMMNJJdBUsvl+ukmBcZYKkX9MDxza1NUO+710a7Ll97MWPCjRv/QI/UIcqE9EWFtTbh5UhKHg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAnkz1yjDmsBKJit5KEoI0ioown21C42SgscdM2BWcWWAiBuFhQXlJxRuxK+75AhrTVmkUvdJSKBF7qfzB9gS8Sldw=="}]},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"0.0.2":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","version":"0.0.2","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@0.0.2","dist":{"shasum":"3609fb6ef418805ce3c317b0bef5df2cddec008b","tarball":"https://registry.npmjs.org/understudy/-/understudy-0.0.2.tgz","integrity":"sha512-qPMB3yVDzvq21crE6rVCtXyCABCYKDUz4ENKOHAp/8NTyvUx4D/W3panXWDVit0jmWCbl6xWH5zlsJbE/Qe+XA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFxhjFk+ZhzBweG430XgY550ickS3T/7jefunl9Eo6HJAiEAzkTCejxzEsb8yVbd9VCwg3YCCdfjPIQRv5B/LpJ8XJI="}]},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"0.1.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","version":"0.1.0","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@0.1.0","dist":{"shasum":"993dbce4d0c5a28b0f60de76deaccdbdc95616de","tarball":"https://registry.npmjs.org/understudy/-/understudy-0.1.0.tgz","integrity":"sha512-a+O2sptUNTMFpKdx6KETEsXOBqKqbMZiMXj7EXqN08ur86NOhGTAqcCA7t4TPDZbCZ1sqGruwCdRP9A2iqBB9Q==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCKKvh61PxSiEITtylKpq+3CrOXrmI1a/szfyAx3ifEggIhAP5+v0zfxxaST3CEv6XBM2juZJPzU9e1XctaiW6AIw0q"}]},"_npmVersion":"1.1.59","_npmUser":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"0.1.1":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","version":"0.1.1","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@0.1.1","dist":{"shasum":"65619ef0c9efa916586cec86ac979c11be4de0d9","tarball":"https://registry.npmjs.org/understudy/-/understudy-0.1.1.tgz","integrity":"sha512-g+TFAqI+eeb+2yKS638K9cPIlyQUbxTLZBzRbOywYWrCFMbUY8lFAQ/WpwTSnEqeVQtTUNhwLZwVyyhMwUwgHQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHNtWkebsf0i2Ic89xe8mJalIgZMM3jV9SNPkSaKaBzbAiEA3rgPfH0zixcFoyVp3O6SG7wHbww6obu6rZiLlcn+C50="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"1.0.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["buzzwords"],"version":"1.0.0","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@1.0.0","dist":{"shasum":"7059d9b828cd137009f11b68e5ed93b03231af40","tarball":"https://registry.npmjs.org/understudy/-/understudy-1.0.0.tgz","integrity":"sha512-CaRFFPT4adaE5mP+npLDuyz2fODUifjDBExI0wItMRDBAGjJb1HNAHD5T1PzrYkqi2AGY6wwU6SwySxZxh9kiQ==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEC+p1O1DHl5sisGKy2nmcX0QPo4XdEvhdwPWOdSXcrGAiBZGfEh6MOE+DnnLQbQOIqswqPISv9y9TwfeLAlQhW8wA=="}]},"_npmVersion":"1.1.59","_npmUser":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"1.0.1":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["buzzwords"],"version":"1.0.1","main":"lib/index.js","dependencies":{},"devDependencies":{},"optionalDependencies":{},"engines":{"node":"*"},"_id":"understudy@1.0.1","dist":{"shasum":"31606cf48d8567fbacfa3285e1cb0e18c4d9ad3e","tarball":"https://registry.npmjs.org/understudy/-/understudy-1.0.1.tgz","integrity":"sha512-TSmDXJIW9shCPeRVcYuC8FtOdxbQtmFGq/uYu8TlBfayRqW6P5CU74UVDsDFohV+18Sz1Jlh9QzRfEgtYTuZiA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCaF7i/zZaqH4Y2fBhZ/E9bOsmGkeZlpjoFjm4idNvvpwIhAJIoILmt4S6rdXWEeZvj4udDzXcJXB1R8Acep33ML1PB"}]},"_npmVersion":"1.1.59","_npmUser":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}],"directories":{}},"1.1.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["buzzwords"],"version":"1.1.0","main":"lib/index.js","repository":{"type":"git","url":"git@github.com:bmeck/understudy"},"dependencies":{},"devDependencies":{},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"_id":"understudy@1.1.0","dist":{"shasum":"051c5248add3cbb39c0e531b2bf1f130c560248e","tarball":"https://registry.npmjs.org/understudy/-/understudy-1.1.0.tgz","integrity":"sha512-p4N2ZLwk4MH4S7m7sodDCgsBb4DVB1CeHlWZuS6i+h5OPTG8QBBACmJIKIyJtRKofni7sGpLzEwXEiO4yDi4Pg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCW+RhWRuw/EWx1MIWgb547gX3IjJrXZ1XwseqaetzX9AIhAK8jzaDNmN50OhkQR6k3AUKo9eVGgdjaaLOTkOz0ZOot"}]},"_npmVersion":"1.1.70","_npmUser":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"}]},"2.0.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["hooks","before","after","flow control"],"version":"2.0.0","main":"index.js","repository":{"type":"git","url":"git@github.com:bmeck/node-understudy"},"dependencies":{},"devDependencies":{},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"gitHead":"db4e59da2a33037b7ad7c0cb0667feab5e055916","bugs":{"url":"https://github.com/bmeck/node-understudy/issues"},"homepage":"https://github.com/bmeck/node-understudy","_id":"understudy@2.0.0","_shasum":"d588c78918139970c469cc587e95945320748ec5","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jcrugzz","email":"jcrugzz@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"dist":{"shasum":"d588c78918139970c469cc587e95945320748ec5","tarball":"https://registry.npmjs.org/understudy/-/understudy-2.0.0.tgz","integrity":"sha512-7BekO3AK6kw1HvBFhkY4ZZKhOgRF2wYkUCzfzWmBTr+nwvxVHT89jsffvPTeZ7smw3EQL+GQm3xL74ySPjfqXA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICBWhYF1rC91YOGVd98iYIq/oDjbZOE4AQB4EW/GCDsIAiEAhvsbFSSbDHkVHqEKQirLdgLwmhKD8ViWbHWZ8/W64pE="}]}},"3.0.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["hooks","before","after","flow control"],"version":"3.0.0","main":"index.js","repository":{"type":"git","url":"git@github.com:bmeck/node-understudy"},"dependencies":{},"devDependencies":{},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"license":"MIT","gitHead":"ba673222dbf17bc64769b2986fe30ec861ae22fb","bugs":{"url":"https://github.com/bmeck/node-understudy/issues"},"homepage":"https://github.com/bmeck/node-understudy","_id":"understudy@3.0.0","_shasum":"9a02f7f41fb79912041a9786a5747a1cd2c9230d","_from":".","_npmVersion":"1.4.28","_npmUser":{"name":"jcrugzz","email":"jcrugzz@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"dist":{"shasum":"9a02f7f41fb79912041a9786a5747a1cd2c9230d","tarball":"https://registry.npmjs.org/understudy/-/understudy-3.0.0.tgz","integrity":"sha512-shohYJgeC0wcN0a9wwjEXUAGZg/I0p3S+mMI363RhXBRK36fZZyvf8t2J+Oh7ubjg9iEPilqAZMU1eR7s7KRrw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEMjcOIgRSazENms50hxVecLZqsL4PsrKLpliMDn/9I1AiBDfTqEatfcQFTEnQBnHs9jwGZYf0XF7g94famekeG7ZA=="}]}},"3.1.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["hooks","before","after","flow control"],"version":"3.1.0","main":"index.js","repository":{"type":"git","url":"git@github.com:bmeck/understudy"},"dependencies":{},"devDependencies":{"accounting":"~0.4.1","benchmark":"~1.0.0","microtime":"~1.0.1"},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"license":"MIT","gitHead":"5557cad9e07ae5d328fda82b66722d06d355cf1b","bugs":{"url":"https://github.com/bmeck/understudy/issues"},"homepage":"https://github.com/bmeck/understudy","_id":"understudy@3.1.0","_shasum":"84df77edd26bc69e1cb1b695d7751942fb787f73","_from":".","_npmVersion":"2.6.1","_nodeVersion":"0.10.36","_npmUser":{"name":"indexzero","email":"charlie.robbins@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"dist":{"shasum":"84df77edd26bc69e1cb1b695d7751942fb787f73","tarball":"https://registry.npmjs.org/understudy/-/understudy-3.1.0.tgz","integrity":"sha512-DvnmxDgeks4695W8SRB1d9e0zIt6HSvoWtXHmWL13WGMMCjzKUPUm+qHbKwVnIWNS/GTi7MZI02+1q8hPzVzKA==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIEGljUOq1UEQuMEXFMVY0hbfKYAlLN5w+ZbU3lZqxam/AiB7f57qv8+LXewCeyOdN8OIe+IVm8hjOnHG0+iWKjbj8w=="}]}},"4.0.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["hooks","before","after","flow control"],"version":"4.0.0","main":"index.js","repository":{"type":"git","url":"git@github.com:bmeck/understudy"},"dependencies":{},"devDependencies":{"accounting":"~0.4.1","benchmark":"~1.0.0","microtime":"~1.0.1"},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"license":"MIT","gitHead":"b322e64b9f1efe2a727b9d76df494b06108950d1","bugs":{"url":"https://github.com/bmeck/understudy/issues"},"homepage":"https://github.com/bmeck/understudy","_id":"understudy@4.0.0","_shasum":"8ec2d09d733c4332987eac6def50b01a4b9a71dd","_from":".","_npmVersion":"2.6.1","_nodeVersion":"0.10.36","_npmUser":{"name":"indexzero","email":"charlie.robbins@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"dist":{"shasum":"8ec2d09d733c4332987eac6def50b01a4b9a71dd","tarball":"https://registry.npmjs.org/understudy/-/understudy-4.0.0.tgz","integrity":"sha512-HIQE1B9806s/JL+01yLO/eLS4kFW7YfVUSks4piMxmIczfz3TmQhk+WX3UnSyzc7QnizaJ+IwMO/V5MkmGt0yw==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIEv7N+WQkyy3SGp0Kv5uGndYHmvETvBxpRoscnYoDK7xAiEAtL3py5UAs06f/j+CXa7cU+wuvrU44SJeNHbt5z1CnPg="}]}},"4.1.0":{"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"name":"understudy","description":"action interceptor for dynamic extensible systems","tags":["hooks","before","after","flow control"],"version":"4.1.0","main":"index.js","repository":{"type":"git","url":"git+ssh://git@github.com/bmeck/understudy.git"},"dependencies":{},"devDependencies":{"accounting":"~0.4.1","benchmark":"~1.0.0","microtime":"^2.0.0"},"optionalDependencies":{},"scripts":{"test":"for SCRIPT in test/*.js; do echo Testing $SCRIPT; node $SCRIPT; done"},"engines":{"node":"*"},"license":"MIT","gitHead":"dc06eac5770435242821a32f685bab91b33004f8","bugs":{"url":"https://github.com/bmeck/understudy/issues"},"homepage":"https://github.com/bmeck/understudy#readme","_id":"understudy@4.1.0","_shasum":"b6d6e9624ccbb7fa2e51969f5be2c748e969ef4a","_from":".","_npmVersion":"2.14.3","_nodeVersion":"4.1.0","_npmUser":{"name":"jcrugzz","email":"jcrugzz@gmail.com"},"maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"dist":{"shasum":"b6d6e9624ccbb7fa2e51969f5be2c748e969ef4a","tarball":"https://registry.npmjs.org/understudy/-/understudy-4.1.0.tgz","integrity":"sha512-pM7KoFRm92pe6ksswZPbUzJAtwo2aUSkR1W13UaTZ2b6LpLGTZJAiYNZQ4iWX4fES3huZUWP+1E0UUC1b3r+kg==","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDDQsiK8y8svbe5Esaf3Y2e8/XapSQFM10jjqgUIMj/+AIgCPdDAX1Mfpv90eDJin5kNuxk2y4GPwm5C0TyLVtKKws="}]}}},"readme":"# Understudy\n\nA means to provide interceptors (i.e. hooks) when performing asynchronous actions.\n\n* **All hooks are asynchronous**\n* * All logic done by `perform`-based actions is asynchronous.\n* * Error first helpers.\n* * Fail fast.\n* **Consistency in arguments provided to hooks & actions**\n* * Hooks can only mutate arguments that they are passed, not the number of arguments.\n* * Use of callback arguments to pass information removes focus on return values to mitigate this potentially odd behavior.\n* **Opt-in behavior.**\n* * Only calls to `.perform(action ...` enable hooking.\n\n![](assets/flow.png)\n\nBy depending on `understudy` you are exposed to four methods: `perform`, `before`, `after` and `waterfall`\n\n#### `.perform(action, arg0, /* arg1, ... */, work, callback)`\n\nThis is the core API for invoking hooks provided by `Understudy`. Each call to `perform` for the same `action` should have a consistent argument signature because this is what will be expected by each of the before and after hooks for the `action`. The overall flow control is:\n\n1. Call all `before` hooks for `action`.\n2. Call `work` function for `action`.\n3. Call all `after hooks for `action`.\n4. Call `callback` with results from `work` function.\n\n#### `.before(action, arg0, /* arg1, ... */, next)`\n\nCalled before the `work` function is executed in perform with _exactly_ the arguments passed to `.perform`. Nothing passed to `next` have an impact on the flow control above **except any error is supplied short-circuits execution to the callback.**\n\n#### `.after(action, arg0, /* arg1, ... */, next)`\n\nCalled after the `work` function is executed in perform with _exactly_ the\narguments passed to `.perform`. Nothing passed to `next` have an impact on the\nflow control above **except any error is supplied short-circuits execution to\nthe callback.** \n\nWhile the above statement is true when using `.perform`, `after` hooks acquire a\n`waterfall` like behavior with `.waterfall` where the result of work function\ngets passed to the `after` hooks. Each after hook is then able to mutate the\narguments passed to the next one. Strongly discouraged to change number of\narguments for your user's sanity.\n\n#### `.waterfall(action, arg0, /* arg1, ... */, work, callback)`\n\nThis is a slightly different `perform` that is very useful for when you have to\nmodify state received from a function in a sequence of configurable hooks.\n\n1. Call all `before` hooks for `action`.\n2. Call `work` function for `action`.\n3. Call all `after hooks for `action` with the result returned from the `work`\n   function.\n4. Call `callback` with results from the `after` hooks execution (if any) and\n   otherwise the results from the `work` function.\n\n\n## Real-world Usage\n\nLet's consider a real-world application with two interceptable actions:\n\n- `start`: Application has started\n- `http:request`: Application has received an incoming HTTP request.\n\nWe could easily implement this `App` behavior in `Understudy`:\n\n``` js\nvar Understudy = require('understudy');\n\nvar App = module.exports = function App() {\n  Understudy.call(this);\n};\n\n//\n// Starts the application after running before and\n// after hooks.\n//\nApp.prototype.start = function (options, callback) {\n  this.perform('start', options, function (next) {\n    //\n    // Here, `options` may have been mutated from the execution\n    // of the before hooks.\n    // ...\n    // Do some other async thing\n    // ...\n    // These arguments are passed to the final callback unless\n    // short-circuited by an error here, or in an after hook.\n    //\n    next(null, options);\n  }, callback);\n};\n\nApp.prototype.handle = function (req, res) {\n  req.times = {\n    start: process.hrtime()\n  };\n\n  this.perform('http:request', req, res, function (next) {\n    req.times.middle = process.hrtime();\n    req.times.begin  = process.hrtime(req.times.start);\n    next();\n  }, function (err) {\n    if (err) {\n      //\n      // Do some error handling.\n      //\n    }\n\n    req.times.total = process.hrtime(req.times.start);\n    req.times.after = process.hrtime(req.times.middle);\n    console.log([\n      'Total time: %s',\n      '  Before hooks: %s',\n      '  After  hooks: %s'\n    ].join('\\n'), format(req.times.total), format(req.times.begin), format(req.times.after));\n\n    res.end();\n  });\n}\n\n//\n// Now we consume a new app with hooks.\n//\nvar http = require('http');\n\nvar app = new App();\napp.before('start', function (options, next) {\n  var server = options.server = http.createServer(function (req, res) {\n    app.handle(req, res);\n  });\n\n  server.listen(options.port, next);\n});\n\napp.after('start', function (options, next) {\n  console.log('App started on %s', options.port);\n});\n\napp.before('http:request', function (req, res, next) {\n  //\n  // Do something asynchronous.\n  //\n  next();\n});\n\napp.start({ port: 8080 }, function () {\n  console.log('ok');\n});\n\n//\n// Format process.hrtime()\n//\nfunction format(s) {\n  return (s[0] * 1e3 + s[1] / 1e6) / 1e3;\n}\n```\n\n## More Examples\n\nSee [the example directory](/example)\n\n### Error handling when **no callback is provided**\n\nEach `before` and `after` hook can provide an optional error to short-circuit evaluation of the flow that would normally follow it. This error will be provided to your `callback`, when supplied. In the event that you DO NOT provide a `callback` and a `before`, `after` or `work` function responds with an `Error` _IT WILL BE IGNORED AND FLOW WILL CONTINUE._ e.g.\n\n``` js\nvar Understudy = require('understudy');\nvar actor = new Understudy();\n\nactor.before('always', function (next) {\n  next(new Error('I always fail'));\n});\n\nactor.after('always', function (next) {\n  console.log('I always get called. NO MATTER WHAT');\n  console.log('BUT, only when no callback is supplied.');\n  next(new Error('Another swallowed error'));\n});\n\nactor.perform('always', function (done) {\n  done(new Error('Errors are ignored here too.'));\n});\n```\n\nIn other words (as in the above example): if you do not supply a callback to your `.perform` then `understudy` will consider all of your `before`, `after` and `work` functions as **\"fire and forget\".**\n\n##### LICENSE: MIT\n##### Author: [Bradley Meck](https://github.com/bmeck)\n##### Contributors: [Jarrett Cruger](https://github.com/jcrugzz), [Charlie Robbins](https://github.com/indexzero)\n","maintainers":[{"name":"bradleymeck","email":"bradley.meck@gmail.com"},{"name":"indexzero","email":"charlie.robbins@gmail.com"},{"name":"jcrugzz","email":"jcrugzz@gmail.com"}],"time":{"modified":"2022-06-28T04:11:27.200Z","created":"2012-08-04T19:38:50.979Z","0.0.1":"2012-08-04T19:38:51.747Z","0.0.2":"2012-08-09T20:26:25.905Z","0.1.0":"2012-08-23T19:58:05.239Z","0.1.1":"2012-08-31T14:18:59.628Z","1.0.0":"2012-10-13T15:33:11.202Z","1.0.1":"2012-10-14T23:14:08.894Z","1.0.2":"2012-10-15T01:12:11.778Z","1.1.0":"2013-01-11T10:07:16.085Z","2.0.0":"2014-12-10T19:25:05.675Z","3.0.0":"2014-12-10T23:25:28.023Z","3.1.0":"2015-03-26T18:45:35.836Z","4.0.0":"2015-05-28T01:44:12.069Z","4.1.0":"2015-09-25T00:53:30.755Z"},"author":{"name":"bradleymeck","email":"bradley.meck@gmail.com"},"repository":{"type":"git","url":"git+ssh://git@github.com/bmeck/understudy.git"},"readmeFilename":"README.md","homepage":"https://github.com/bmeck/understudy#readme","bugs":{"url":"https://github.com/bmeck/understudy/issues"},"license":"MIT","users":{"jeseab":true}}