|
1 | 1 | ## Description
|
2 | 2 |
|
| 3 | +Purpose: learn how to wrap the interfaces and make wrapper flexible enough to |
| 4 | +wrap unknown interface with just one assumption that callbacks should be last |
| 5 | +argument of asynchronous functions. As an example, we have `setTimeout` wrapped |
| 6 | +and as a result we will wrap a whole interface of the file system `fs`. |
| 7 | + |
3 | 8 | ## Files
|
4 | 9 |
|
5 | 10 | * `framework.js` - small piece of the framework, just to demonstrate wrapper
|
|
9 | 14 |
|
10 | 15 | From the command line, type: `node application` then `node framework`, compare
|
11 | 16 | output, read code in `framework.js` and `application.js`, try to understand
|
12 |
| -how wrapper works for `setTimeout` |
| 17 | +how wrapper works for `setTimeout`. |
13 | 18 |
|
14 | 19 | ## Tasks
|
15 | 20 |
|
| 21 | +1. Learn how `setTimeout` is wrapped in example: `framework.js`. Now we will |
| 22 | +try to wrap module fs. We can iterat all of its functions by following code: |
| 23 | +`for (var key in fs) {...}` and replace its function with wrapped ones. We need |
| 24 | +a closure function and it should be universal to wrap any function in fs |
| 25 | +interface. The purpose of this example wrapper is to log all calls to the file |
| 26 | +system in a file indicating the time, a function name, its arguments, and if |
| 27 | +the function has also callback, it is necessary to intercept it too and wrap |
| 28 | +this callback, logging callback calls. |
| 29 | +This task can be divided into a few steps. |
| 30 | +2. Remove `setTimeout` example from `application.js` and replace it with the |
| 31 | +following code: |
| 32 | + ```JavaScript |
| 33 | + var fileName = './README.md'; |
| 34 | + console.log('Application going to read ' + fileName); |
| 35 | + fs.readFile(fileName, function(err, src) { |
| 36 | + console.log('File ' + fileName + ' size ' + src.length); |
| 37 | + }); |
| 38 | + ``` |
| 39 | +This example contains a call to `fs.readFile`. In next steps we will change the |
| 40 | +behavior of the code changing `framework.js` and wrapping all `fs` functions. |
| 41 | +Let`s run `node framework` and make sure that it reads th file displays its |
| 42 | +length. |
| 43 | +3. Next step is preparing function `cloneInterface(interfaceName)` for cloning |
| 44 | +all keys from given library into new interface. So we can pass its result |
| 45 | +(cloned `fs`) to sandbox instead of `fs`. Clonning function example: |
| 46 | + ```JavaScript |
| 47 | + function cloneInterface(anInterface) { |
| 48 | + var clone = {}; |
| 49 | + for (var key in anInterface) { |
| 50 | + clone[key] = anInterface[key]; |
| 51 | + } |
| 52 | + return clone; |
| 53 | + } |
| 54 | + ``` |
| 55 | +4. After that we can add wrapper `wrapFunction(fnName, fn)` with 2 arguments: |
| 56 | +name of the function and link to a function itself. It returns `wrapper` - |
| 57 | +closure function. Closure `wrapper` is a newly created function with the help |
| 58 | +of functional inheritance, so it will see `fnName`, `fn` in its context. Thus |
| 59 | +we can pass all arguments from wrapper into original function as you see in |
| 60 | +example: |
| 61 | + ```JavaScript |
| 62 | + function wrapFunction(fnName, fn) { |
| 63 | + return function wrapper() { |
| 64 | + var args = []; |
| 65 | + Array.prototype.push.apply(args, arguments); |
| 66 | + console.log('Call: ' + fnName); |
| 67 | + console.dir(args); |
| 68 | + fn.apply(undefined, args); |
| 69 | + } |
| 70 | + } |
| 71 | + ``` |
| 72 | +5. Now should detect do we have `callback` argument as a last argument of |
| 73 | +function call, we can do that by `typeof()` comparing to `function`. If we have |
| 74 | +`callback`, we need to wrap it too, so pass ours function instead of `callback` |
| 75 | +and then call ariginal `callback` from this function. |
| 76 | +6. Then we can call other functions of `fs` interface from `application.js` and |
| 77 | +try to run wrapped code. |
| 78 | +7. Add timers in `application.js` and make multiple calls working with files. So |
| 79 | +we will model a real application random file system access. Then we can collect |
| 80 | +some statistics from `framework.js` and print it every 30 seconds. For example, |
| 81 | +you can collect following parameters: |
| 82 | + - number of function calls, |
| 83 | + - number of callbacks, |
| 84 | + - average function completion speed, |
| 85 | + - average return rate of callbacks, |
| 86 | + - total amount of data read from the disk, |
| 87 | + - total amount of recorded data, |
| 88 | + - average read and write speed, |
| 89 | + etc. |
| 90 | + |
| 91 | +Save your results to github, we will need it in next labs, for example we can |
| 92 | +transfer overriden wrapped calls (fs operations) to another process and another |
| 93 | +server. In such a way we can create distributed application. |
| 94 | + |
16 | 95 | ## Additional tasks
|
0 commit comments