root / HServer / 00.Server / 00.Program / node_modules / kareem / README.md
이력 | 보기 | 이력해설 | 다운로드 (8.99 KB)
1 | 39 | HKM | # kareem |
---|---|---|---|
2 | |||
3 | [](https://travis-ci.org/vkarpov15/kareem) |
||
4 | [](https://coveralls.io/r/vkarpov15/kareem) |
||
5 | |||
6 | 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. |
||
7 | |||
8 | 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) |
||
9 | |||
10 | <img src="http://upload.wikimedia.org/wikipedia/commons/0/00/Kareem-Abdul-Jabbar_Lipofsky.jpg" width="220"> |
||
11 | |||
12 | # API |
||
13 | |||
14 | ## pre hooks |
||
15 | |||
16 | Much like [hooks](https://npmjs.org/package/hooks), kareem lets you define |
||
17 | pre and post hooks: pre hooks are called before a given function executes. |
||
18 | Unlike hooks, kareem stores hooks and other internal state in a separate |
||
19 | object, rather than relying on inheritance. Furthermore, kareem exposes |
||
20 | an `execPre()` function that allows you to execute your pre hooks when |
||
21 | appropriate, giving you more fine-grained control over your function hooks. |
||
22 | |||
23 | |||
24 | #### It runs without any hooks specified |
||
25 | |||
26 | ```javascript |
||
27 | |||
28 | hooks.execPre('cook', null, function() { |
||
29 | done(); |
||
30 | }); |
||
31 | |||
32 | ``` |
||
33 | |||
34 | #### It runs basic serial pre hooks |
||
35 | |||
36 | pre hook functions take one parameter, a "done" function that you execute |
||
37 | when your pre hook is finished. |
||
38 | |||
39 | |||
40 | ```javascript |
||
41 | |||
42 | var count = 0; |
||
43 | |||
44 | hooks.pre('cook', function(done) { |
||
45 | ++count; |
||
46 | done(); |
||
47 | }); |
||
48 | |||
49 | hooks.execPre('cook', null, function() { |
||
50 | assert.equal(1, count); |
||
51 | done(); |
||
52 | }); |
||
53 | |||
54 | ``` |
||
55 | |||
56 | #### It can run multipe pre hooks |
||
57 | |||
58 | ```javascript |
||
59 | |||
60 | var count1 = 0; |
||
61 | var count2 = 0; |
||
62 | |||
63 | hooks.pre('cook', function(done) { |
||
64 | ++count1; |
||
65 | done(); |
||
66 | }); |
||
67 | |||
68 | hooks.pre('cook', function(done) { |
||
69 | ++count2; |
||
70 | done(); |
||
71 | }); |
||
72 | |||
73 | hooks.execPre('cook', null, function() { |
||
74 | assert.equal(1, count1); |
||
75 | assert.equal(1, count2); |
||
76 | done(); |
||
77 | }); |
||
78 | |||
79 | ``` |
||
80 | |||
81 | #### It can run fully synchronous pre hooks |
||
82 | |||
83 | If your pre hook function takes no parameters, its assumed to be |
||
84 | fully synchronous. |
||
85 | |||
86 | |||
87 | ```javascript |
||
88 | |||
89 | var count1 = 0; |
||
90 | var count2 = 0; |
||
91 | |||
92 | hooks.pre('cook', function() { |
||
93 | ++count1; |
||
94 | }); |
||
95 | |||
96 | hooks.pre('cook', function() { |
||
97 | ++count2; |
||
98 | }); |
||
99 | |||
100 | hooks.execPre('cook', null, function(error) { |
||
101 | assert.equal(null, error); |
||
102 | assert.equal(1, count1); |
||
103 | assert.equal(1, count2); |
||
104 | done(); |
||
105 | }); |
||
106 | |||
107 | ``` |
||
108 | |||
109 | #### It properly attaches context to pre hooks |
||
110 | |||
111 | Pre save hook functions are bound to the second parameter to `execPre()` |
||
112 | |||
113 | |||
114 | ```javascript |
||
115 | |||
116 | hooks.pre('cook', function(done) { |
||
117 | this.bacon = 3; |
||
118 | done(); |
||
119 | }); |
||
120 | |||
121 | hooks.pre('cook', function(done) { |
||
122 | this.eggs = 4; |
||
123 | done(); |
||
124 | }); |
||
125 | |||
126 | var obj = { bacon: 0, eggs: 0 }; |
||
127 | |||
128 | // In the pre hooks, `this` will refer to `obj` |
||
129 | hooks.execPre('cook', obj, function(error) { |
||
130 | assert.equal(null, error); |
||
131 | assert.equal(3, obj.bacon); |
||
132 | assert.equal(4, obj.eggs); |
||
133 | done(); |
||
134 | }); |
||
135 | |||
136 | ``` |
||
137 | |||
138 | #### It can execute parallel (async) pre hooks |
||
139 | |||
140 | Like the hooks module, you can declare "async" pre hooks - these take two |
||
141 | parameters, the functions `next()` and `done()`. `next()` passes control to |
||
142 | the next pre hook, but the underlying function won't be called until all |
||
143 | async pre hooks have called `done()`. |
||
144 | |||
145 | |||
146 | ```javascript |
||
147 | |||
148 | hooks.pre('cook', true, function(next, done) { |
||
149 | this.bacon = 3; |
||
150 | next(); |
||
151 | setTimeout(function() { |
||
152 | done(); |
||
153 | }, 5); |
||
154 | }); |
||
155 | |||
156 | hooks.pre('cook', true, function(next, done) { |
||
157 | next(); |
||
158 | var _this = this; |
||
159 | setTimeout(function() { |
||
160 | _this.eggs = 4; |
||
161 | done(); |
||
162 | }, 10); |
||
163 | }); |
||
164 | |||
165 | hooks.pre('cook', function(next) { |
||
166 | this.waffles = false; |
||
167 | next(); |
||
168 | }); |
||
169 | |||
170 | var obj = { bacon: 0, eggs: 0 }; |
||
171 | |||
172 | hooks.execPre('cook', obj, function() { |
||
173 | assert.equal(3, obj.bacon); |
||
174 | assert.equal(4, obj.eggs); |
||
175 | assert.equal(false, obj.waffles); |
||
176 | done(); |
||
177 | }); |
||
178 | |||
179 | ``` |
||
180 | |||
181 | #### It supports returning a promise |
||
182 | |||
183 | You can also return a promise from your pre hooks instead of calling |
||
184 | `next()`. When the returned promise resolves, kareem will kick off the |
||
185 | next middleware. |
||
186 | |||
187 | |||
188 | ```javascript |
||
189 | |||
190 | hooks.pre('cook', function() { |
||
191 | return new Promise(resolve => { |
||
192 | setTimeout(() => { |
||
193 | this.bacon = 3; |
||
194 | resolve(); |
||
195 | }, 100); |
||
196 | }); |
||
197 | }); |
||
198 | |||
199 | var obj = { bacon: 0 }; |
||
200 | |||
201 | hooks.execPre('cook', obj, function() { |
||
202 | assert.equal(3, obj.bacon); |
||
203 | done(); |
||
204 | }); |
||
205 | |||
206 | ``` |
||
207 | |||
208 | ## post hooks |
||
209 | |||
210 | #### It runs without any hooks specified |
||
211 | |||
212 | ```javascript |
||
213 | |||
214 | hooks.execPost('cook', null, [1], function(error, eggs) { |
||
215 | assert.ifError(error); |
||
216 | assert.equal(1, eggs); |
||
217 | done(); |
||
218 | }); |
||
219 | |||
220 | ``` |
||
221 | |||
222 | #### It executes with parameters passed in |
||
223 | |||
224 | ```javascript |
||
225 | |||
226 | hooks.post('cook', function(eggs, bacon, callback) { |
||
227 | assert.equal(1, eggs); |
||
228 | assert.equal(2, bacon); |
||
229 | callback(); |
||
230 | }); |
||
231 | |||
232 | hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { |
||
233 | assert.ifError(error); |
||
234 | assert.equal(1, eggs); |
||
235 | assert.equal(2, bacon); |
||
236 | done(); |
||
237 | }); |
||
238 | |||
239 | ``` |
||
240 | |||
241 | #### It can use synchronous post hooks |
||
242 | |||
243 | ```javascript |
||
244 | |||
245 | var execed = {}; |
||
246 | |||
247 | hooks.post('cook', function(eggs, bacon) { |
||
248 | execed.first = true; |
||
249 | assert.equal(1, eggs); |
||
250 | assert.equal(2, bacon); |
||
251 | }); |
||
252 | |||
253 | hooks.post('cook', function(eggs, bacon, callback) { |
||
254 | execed.second = true; |
||
255 | assert.equal(1, eggs); |
||
256 | assert.equal(2, bacon); |
||
257 | callback(); |
||
258 | }); |
||
259 | |||
260 | hooks.execPost('cook', null, [1, 2], function(error, eggs, bacon) { |
||
261 | assert.ifError(error); |
||
262 | assert.equal(2, Object.keys(execed).length); |
||
263 | assert.ok(execed.first); |
||
264 | assert.ok(execed.second); |
||
265 | assert.equal(1, eggs); |
||
266 | assert.equal(2, bacon); |
||
267 | done(); |
||
268 | }); |
||
269 | |||
270 | ``` |
||
271 | |||
272 | ## wrap() |
||
273 | |||
274 | #### It wraps pre and post calls into one call |
||
275 | |||
276 | ```javascript |
||
277 | |||
278 | hooks.pre('cook', true, function(next, done) { |
||
279 | this.bacon = 3; |
||
280 | next(); |
||
281 | setTimeout(function() { |
||
282 | done(); |
||
283 | }, 5); |
||
284 | }); |
||
285 | |||
286 | hooks.pre('cook', true, function(next, done) { |
||
287 | next(); |
||
288 | var _this = this; |
||
289 | setTimeout(function() { |
||
290 | _this.eggs = 4; |
||
291 | done(); |
||
292 | }, 10); |
||
293 | }); |
||
294 | |||
295 | hooks.pre('cook', function(next) { |
||
296 | this.waffles = false; |
||
297 | next(); |
||
298 | }); |
||
299 | |||
300 | hooks.post('cook', function(obj) { |
||
301 | obj.tofu = 'no'; |
||
302 | }); |
||
303 | |||
304 | var obj = { bacon: 0, eggs: 0 }; |
||
305 | |||
306 | var args = [obj]; |
||
307 | args.push(function(error, result) { |
||
308 | assert.ifError(error); |
||
309 | assert.equal(null, error); |
||
310 | assert.equal(3, obj.bacon); |
||
311 | assert.equal(4, obj.eggs); |
||
312 | assert.equal(false, obj.waffles); |
||
313 | assert.equal('no', obj.tofu); |
||
314 | |||
315 | assert.equal(obj, result); |
||
316 | done(); |
||
317 | }); |
||
318 | |||
319 | hooks.wrap( |
||
320 | 'cook', |
||
321 | function(o, callback) { |
||
322 | assert.equal(3, obj.bacon); |
||
323 | assert.equal(4, obj.eggs); |
||
324 | assert.equal(false, obj.waffles); |
||
325 | assert.equal(undefined, obj.tofu); |
||
326 | callback(null, o); |
||
327 | }, |
||
328 | obj, |
||
329 | args); |
||
330 | |||
331 | ``` |
||
332 | |||
333 | ## createWrapper() |
||
334 | |||
335 | #### It wraps wrap() into a callable function |
||
336 | |||
337 | ```javascript |
||
338 | |||
339 | hooks.pre('cook', true, function(next, done) { |
||
340 | this.bacon = 3; |
||
341 | next(); |
||
342 | setTimeout(function() { |
||
343 | done(); |
||
344 | }, 5); |
||
345 | }); |
||
346 | |||
347 | hooks.pre('cook', true, function(next, done) { |
||
348 | next(); |
||
349 | var _this = this; |
||
350 | setTimeout(function() { |
||
351 | _this.eggs = 4; |
||
352 | done(); |
||
353 | }, 10); |
||
354 | }); |
||
355 | |||
356 | hooks.pre('cook', function(next) { |
||
357 | this.waffles = false; |
||
358 | next(); |
||
359 | }); |
||
360 | |||
361 | hooks.post('cook', function(obj) { |
||
362 | obj.tofu = 'no'; |
||
363 | }); |
||
364 | |||
365 | var obj = { bacon: 0, eggs: 0 }; |
||
366 | |||
367 | var cook = hooks.createWrapper( |
||
368 | 'cook', |
||
369 | function(o, callback) { |
||
370 | assert.equal(3, obj.bacon); |
||
371 | assert.equal(4, obj.eggs); |
||
372 | assert.equal(false, obj.waffles); |
||
373 | assert.equal(undefined, obj.tofu); |
||
374 | callback(null, o); |
||
375 | }, |
||
376 | obj); |
||
377 | |||
378 | cook(obj, function(error, result) { |
||
379 | assert.ifError(error); |
||
380 | assert.equal(3, obj.bacon); |
||
381 | assert.equal(4, obj.eggs); |
||
382 | assert.equal(false, obj.waffles); |
||
383 | assert.equal('no', obj.tofu); |
||
384 | |||
385 | assert.equal(obj, result); |
||
386 | done(); |
||
387 | }); |
||
388 | |||
389 | ``` |
||
390 | |||
391 | ## clone() |
||
392 | |||
393 | #### It clones a Kareem object |
||
394 | |||
395 | ```javascript |
||
396 | |||
397 | var k1 = new Kareem(); |
||
398 | k1.pre('cook', function() {}); |
||
399 | k1.post('cook', function() {}); |
||
400 | |||
401 | var k2 = k1.clone(); |
||
402 | assert.deepEqual(['cook'], Object.keys(k2._pres)); |
||
403 | assert.deepEqual(['cook'], Object.keys(k2._posts)); |
||
404 | |||
405 | ``` |
||
406 | |||
407 | ## merge() |
||
408 | |||
409 | #### It pulls hooks from another Kareem object |
||
410 | |||
411 | ```javascript |
||
412 | |||
413 | var k1 = new Kareem(); |
||
414 | var test1 = function() {}; |
||
415 | k1.pre('cook', test1); |
||
416 | k1.post('cook', function() {}); |
||
417 | |||
418 | var k2 = new Kareem(); |
||
419 | var test2 = function() {}; |
||
420 | k2.pre('cook', test2); |
||
421 | var k3 = k2.merge(k1); |
||
422 | assert.equal(k3._pres['cook'].length, 2); |
||
423 | assert.equal(k3._pres['cook'][0].fn, test2); |
||
424 | assert.equal(k3._pres['cook'][1].fn, test1); |
||
425 | assert.equal(k3._posts['cook'].length, 1); |
||
426 | |||
427 | ``` |