1 | # wagner-core
|
2 |
|
3 | Dependency-injection-inspired async framework that doubles as an isomorphic AngularJS-compatible dependency injector.
|
4 |
|
5 | ## API
|
6 |
|
7 | ### `wagner.invokeAsync()`
|
8 |
|
9 | `invokeAsync()` is the primary function you will use to execute
|
10 | async code with Wagner. It takes as arguments a function that
|
11 | takes an error and a list of parameters, and a map of *locals*.
|
12 |
|
13 | ##### It allows you to execute async tasks based on parameter names
|
14 |
|
15 | Wagner's most basic functionality is to register an async
|
16 | task by name, and then utilize the value computed by the
|
17 | async task in subsequent tasks.
|
18 |
|
19 | ```
|
20 | wagner.task('eggs', function(callback) {
|
21 | setTimeout(function() {
|
22 | callback(null, 'done cooking!');
|
23 | }, 5);
|
24 | });
|
25 |
|
26 | wagner.invokeAsync(function(error, eggs) {
|
27 | assert.ok(!error);
|
28 | assert.equal(eggs, 'done cooking!');
|
29 | done();
|
30 | }, {});
|
31 | ```
|
32 |
|
33 | ##### It allows you to use locals
|
34 |
|
35 | *locals* are values specific to a particular execution of
|
36 | `invokeAsync()`. They may be utilized by any task in the
|
37 | task graph.
|
38 |
|
39 | ```
|
40 | wagner.task('eggs', function(number, callback) {
|
41 | setTimeout(function() {
|
42 | callback(null, 'finished making ' + number + ' eggs');
|
43 | }, 5);
|
44 | });
|
45 |
|
46 | wagner.invokeAsync(function(error, eggs) {
|
47 | assert.ok(!error);
|
48 | assert.equal(eggs, 'finished making 4 eggs');
|
49 | done();
|
50 | }, {
|
51 | number: 4
|
52 | });
|
53 | ```
|
54 |
|
55 | ##### It executes tasks with maximum parallelization
|
56 |
|
57 | Tasks can rely on each other, and each task is executed as soon
|
58 | as all its dependencies are met.
|
59 |
|
60 | ```
|
61 | var executed = {};
|
62 |
|
63 | wagner.task('pan', function(callback) {
|
64 | setTimeout(function() {
|
65 | executed['pan'] = true;
|
66 | callback(null, 'finished heating pan');
|
67 | }, 5);
|
68 | });
|
69 |
|
70 | wagner.task('eggs', function(counts, pan, callback) {
|
71 | assert.ok(!executed['bacon']);
|
72 | setTimeout(function() {
|
73 | executed['eggs'] = true;
|
74 | callback(null, 'finished making ' + counts.eggs + ' eggs');
|
75 | }, 5);
|
76 | });
|
77 |
|
78 | wagner.task('bacon', function(counts, pan, callback) {
|
79 | assert.ok(!executed['eggs']);
|
80 | setTimeout(function() {
|
81 | executed['bacon'] = true;
|
82 | callback(null, 'finished making ' + counts.bacon + ' bacon strips');
|
83 | }, 5);
|
84 | });
|
85 |
|
86 | wagner.invokeAsync(
|
87 | function(error, eggs, bacon) {
|
88 | assert.ok(!error);
|
89 | assert.ok(executed['pan']);
|
90 | assert.equal(eggs, 'finished making 4 eggs');
|
91 | assert.equal(bacon, 'finished making 3 bacon strips');
|
92 | done();
|
93 | }, {
|
94 | counts: {
|
95 | eggs: 4,
|
96 | bacon: 3
|
97 | }
|
98 | });
|
99 | ```
|
100 |
|
101 | ##### It bubbles up the first error
|
102 |
|
103 | If any task in the execution tree returns an error, execution
|
104 | is stopped immediately and the function is called with the error
|
105 | as the first parameter.
|
106 |
|
107 | ```
|
108 | wagner.task('eggs', function(callback) {
|
109 | setTimeout(function() {
|
110 | callback('no eggs left!');
|
111 | }, 5);
|
112 | });
|
113 |
|
114 | wagner.task('bacon', function(callback) {
|
115 | setTimeout(function() {
|
116 | callback('no bacon left!');
|
117 | }, 25);
|
118 | });
|
119 |
|
120 | wagner.invokeAsync(
|
121 | function(error, eggs, bacon) {
|
122 | assert.equal(error, 'no eggs left!');
|
123 | assert.ok(!eggs);
|
124 | assert.ok(!bacon);
|
125 | done();
|
126 | }, {});
|
127 | ```
|
128 |
|
129 | ##### It returns an Promises/A+ conformant promise
|
130 |
|
131 | For compatibility with the `yield` keyword, as well as chaining,
|
132 | `invokeAsync()` returns a
|
133 | [bluebird](https://www.npmjs.org/package/bluebird) promise that is
|
134 | rejected if an error occurs in any of the tasks, or fulfilled with
|
135 | the return value of the provided function otherwise.
|
136 |
|
137 | ```
|
138 | wagner.task('valkyrie', function(callback) {
|
139 | setTimeout(function() {
|
140 | callback(null, 'valkyrie');
|
141 | }, 0);
|
142 | });
|
143 |
|
144 | var promise = wagner.invokeAsync(function(error, valkyrie) {
|
145 | return valkyrie;
|
146 | }, {});
|
147 |
|
148 | promise.then(function(v) {
|
149 | assert.equal(v, 'valkyrie');
|
150 | done();
|
151 | });
|
152 | ```
|
153 |
|
154 | ### `wagner.invoke()`
|
155 |
|
156 | `invoke()` is the synchronous version of `invokeAsync()`. It will
|
157 | *only* execute sync tasks (tasks that don't take a parameter named
|
158 | 'callback' or 'cb') and throw an error if there are any async tasks.
|
159 |
|
160 | ##### It executes sync tasks and returns the return value of the provided function
|
161 |
|
162 | ```
|
163 | wagner.task('tristan', function() {
|
164 | return 'tristan';
|
165 | });
|
166 |
|
167 | wagner.task('isolde', function() {
|
168 | return 'isolde';
|
169 | });
|
170 |
|
171 | var e;
|
172 | var t;
|
173 | var i;
|
174 | var returnValue = wagner.invoke(function(error, tristan, isolde) {
|
175 | e = error;
|
176 | t = tristan;
|
177 | i = isolde;
|
178 |
|
179 | return 'done';
|
180 | });
|
181 |
|
182 | assert.ok(!e);
|
183 | assert.equal(t, 'tristan');
|
184 | assert.equal(i, 'isolde');
|
185 | assert.equal(returnValue, 'done');
|
186 | ```
|
187 |
|
188 | ### `wagner.parallel()`
|
189 |
|
190 | For convenience, Wagner includes its own `.parallel()` function for
|
191 | executing a collection of async functions in parallel.
|
192 |
|
193 | ##### It takes a map and executes a function for all key/value pairs
|
194 |
|
195 | ```
|
196 | wagner.parallel({
|
197 | first: 'eggs',
|
198 | second: 'bacon'
|
199 | },
|
200 | function(value, key, callback) {
|
201 | callback(null, value.toUpperCase());
|
202 | },
|
203 | function(error, results) {
|
204 | assert.ok(!error);
|
205 | assert.equal(results.first.result, 'EGGS');
|
206 | assert.equal(results.second.result, 'BACON');
|
207 | done();
|
208 | });
|
209 | ```
|
210 |
|