|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428 |
- # kareem
-
- [![Build Status](https://travis-ci.org/vkarpov15/kareem.svg?branch=master)](https://travis-ci.org/vkarpov15/kareem)
- [![Coverage Status](https://img.shields.io/coveralls/vkarpov15/kareem.svg)](https://coveralls.io/r/vkarpov15/kareem)
-
- Re-imagined take on the [hooks](http://npmjs.org/package/hooks) module, meant to offer additional flexibility in allowing you to execute hooks whenever necessary, as opposed to simply wrapping a single function.
-
- Named for the NBA's all-time leading scorer Kareem Abdul-Jabbar, known for his mastery of the [hook shot](http://en.wikipedia.org/wiki/Kareem_Abdul-Jabbar#Skyhook)
-
- <img src="http://upload.wikimedia.org/wikipedia/commons/0/00/Kareem-Abdul-Jabbar_Lipofsky.jpg" width="220">
-
- # API
-
- ## pre hooks
-
- Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define
- pre and post hooks: pre hooks are called before a given function executes.
- Unlike hooks, kareem stores hooks and other internal state in a separate
- object, rather than relying on inheritance. Furthermore, kareem exposes
- an `execPre()` function that allows you to execute your pre hooks when
- appropriate, giving you more fine-grained control over your function hooks.
-
-
- #### It runs without any hooks specified
-
- ```javascript
-
- hooks.execPre('cook', null, function() {
- done();
- });
-
- ```
-
- #### It runs basic serial pre hooks
-
- pre hook functions take one parameter, a "done" function that you execute
- when your pre hook is finished.
-
-
- ```javascript
-
- var count = 0;
-
- hooks.pre('cook', function(done) {
- ++count;
- done();
- });
-
- hooks.execPre('cook', null, function() {
- assert.equal(1, count);
- done();
- });
-
- ```
-
- #### It can run multipe pre hooks
-
- ```javascript
-
- var count1 = 0;
- var count2 = 0;
-
- hooks.pre('cook', function(done) {
- ++count1;
- done();
- });
-
- hooks.pre('cook', function(done) {
- ++count2;
- done();
- });
-
- hooks.execPre('cook', null, function() {
- assert.equal(1, count1);
- assert.equal(1, count2);
- done();
- });
-
- ```
-
- #### It can run fully synchronous pre hooks
-
- If your pre hook function takes no parameters, its assumed to be
- fully synchronous.
-
-
- ```javascript
-
- var count1 = 0;
- var count2 = 0;
-
- hooks.pre('cook', function() {
- ++count1;
- });
-
- hooks.pre('cook', function() {
- ++count2;
- });
-
- hooks.execPre('cook', null, function(error) {
- assert.equal(null, error);
- assert.equal(1, count1);
- assert.equal(1, count2);
- done();
- });
-
- ```
-
- #### It properly attaches context to pre hooks
-
- Pre save hook functions are bound to the second parameter to `execPre()`
-
-
- ```javascript
-
- hooks.pre('cook', function(done) {
- this.bacon = 3;
- done();
- });
-
- hooks.pre('cook', function(done) {
- this.eggs = 4;
- done();
- });
-
- var obj = { bacon: 0, eggs: 0 };
-
- // In the pre hooks, `this` will refer to `obj`
- hooks.execPre('cook', obj, function(error) {
- assert.equal(null, error);
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- done();
- });
-
- ```
-
- #### It can execute parallel (async) pre hooks
-
- Like the hooks module, you can declare "async" pre hooks - these take two
- parameters, the functions `next()` and `done()`. `next()` passes control to
- the next pre hook, but the underlying function won't be called until all
- async pre hooks have called `done()`.
-
-
- ```javascript
-
- hooks.pre('cook', true, function(next, done) {
- this.bacon = 3;
- next();
- setTimeout(function() {
- done();
- }, 5);
- });
-
- hooks.pre('cook', true, function(next, done) {
- next();
- var _this = this;
- setTimeout(function() {
- _this.eggs = 4;
- done();
- }, 10);
- });
-
- hooks.pre('cook', function(next) {
- this.waffles = false;
- next();
- });
-
- var obj = { bacon: 0, eggs: 0 };
-
- hooks.execPre('cook', obj, function() {
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- assert.equal(false, obj.waffles);
- done();
- });
-
- ```
-
- #### It supports returning a promise
-
- You can also return a promise from your pre hooks instead of calling
- `next()`. When the returned promise resolves, kareem will kick off the
- next middleware.
-
-
- ```javascript
-
- hooks.pre('cook', function() {
- return new Promise(resolve => {
- setTimeout(() => {
- this.bacon = 3;
- resolve();
- }, 100);
- });
- });
-
- var obj = { bacon: 0 };
-
- hooks.execPre('cook', obj, function() {
- assert.equal(3, obj.bacon);
- done();
- });
-
- ```
-
- ## post hooks
-
- #### It runs without any hooks specified
-
- ```javascript
-
- hooks.execPost('cook', null, [1], function(error, eggs) {
- assert.ifError(error);
- assert.equal(1, eggs);
- done();
- });
-
- ```
-
- #### It executes with parameters passed in
-
- ```javascript
-
- hooks.post('cook', function(eggs, bacon, callback) {
- assert.equal(1, eggs);
- assert.equal(2, bacon);
- callback();
- });
-
- hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
- assert.ifError(error);
- assert.equal(1, eggs);
- assert.equal(2, bacon);
- done();
- });
-
- ```
-
- #### It can use synchronous post hooks
-
- ```javascript
-
- var execed = {};
-
- hooks.post('cook', function(eggs, bacon) {
- execed.first = true;
- assert.equal(1, eggs);
- assert.equal(2, bacon);
- });
-
- hooks.post('cook', function(eggs, bacon, callback) {
- execed.second = true;
- assert.equal(1, eggs);
- assert.equal(2, bacon);
- callback();
- });
-
- hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) {
- assert.ifError(error);
- assert.equal(2, Object.keys(execed).length);
- assert.ok(execed.first);
- assert.ok(execed.second);
- assert.equal(1, eggs);
- assert.equal(2, bacon);
- done();
- });
-
- ```
-
- ## wrap()
-
- #### It wraps pre and post calls into one call
-
- ```javascript
-
- hooks.pre('cook', true, function(next, done) {
- this.bacon = 3;
- next();
- setTimeout(function() {
- done();
- }, 5);
- });
-
- hooks.pre('cook', true, function(next, done) {
- next();
- var _this = this;
- setTimeout(function() {
- _this.eggs = 4;
- done();
- }, 10);
- });
-
- hooks.pre('cook', function(next) {
- this.waffles = false;
- next();
- });
-
- hooks.post('cook', function(obj) {
- obj.tofu = 'no';
- });
-
- var obj = { bacon: 0, eggs: 0 };
-
- var args = [obj];
- args.push(function(error, result) {
- assert.ifError(error);
- assert.equal(null, error);
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- assert.equal(false, obj.waffles);
- assert.equal('no', obj.tofu);
-
- assert.equal(obj, result);
- done();
- });
-
- hooks.wrap(
- 'cook',
- function(o, callback) {
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- assert.equal(false, obj.waffles);
- assert.equal(undefined, obj.tofu);
- callback(null, o);
- },
- obj,
- args);
-
- ```
-
- ## createWrapper()
-
- #### It wraps wrap() into a callable function
-
- ```javascript
-
- hooks.pre('cook', true, function(next, done) {
- this.bacon = 3;
- next();
- setTimeout(function() {
- done();
- }, 5);
- });
-
- hooks.pre('cook', true, function(next, done) {
- next();
- var _this = this;
- setTimeout(function() {
- _this.eggs = 4;
- done();
- }, 10);
- });
-
- hooks.pre('cook', function(next) {
- this.waffles = false;
- next();
- });
-
- hooks.post('cook', function(obj) {
- obj.tofu = 'no';
- });
-
- var obj = { bacon: 0, eggs: 0 };
-
- var cook = hooks.createWrapper(
- 'cook',
- function(o, callback) {
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- assert.equal(false, obj.waffles);
- assert.equal(undefined, obj.tofu);
- callback(null, o);
- },
- obj);
-
- cook(obj, function(error, result) {
- assert.ifError(error);
- assert.equal(3, obj.bacon);
- assert.equal(4, obj.eggs);
- assert.equal(false, obj.waffles);
- assert.equal('no', obj.tofu);
-
- assert.equal(obj, result);
- done();
- });
-
- ```
-
- ## clone()
-
- #### It clones a Kareem object
-
- ```javascript
-
- var k1 = new Kareem();
- k1.pre('cook', function() {});
- k1.post('cook', function() {});
-
- var k2 = k1.clone();
- assert.deepEqual(['cook'], Object.keys(k2._pres));
- assert.deepEqual(['cook'], Object.keys(k2._posts));
-
- ```
-
- ## merge()
-
- #### It pulls hooks from another Kareem object
-
- ```javascript
-
- var k1 = new Kareem();
- var test1 = function() {};
- k1.pre('cook', test1);
- k1.post('cook', function() {});
-
- var k2 = new Kareem();
- var test2 = function() {};
- k2.pre('cook', test2);
- var k3 = k2.merge(k1);
- assert.equal(k3._pres['cook'].length, 2);
- assert.equal(k3._pres['cook'][0].fn, test2);
- assert.equal(k3._pres['cook'][1].fn, test1);
- assert.equal(k3._posts['cook'].length, 1);
-
- ```
-
|