Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit c6202a1

Browse files
committed
feat: add decorator syntax
1 parent 81d5f49 commit c6202a1

5 files changed

Lines changed: 118 additions & 56 deletions

File tree

README.md

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,13 @@ someZone.fork({
113113

114114
### Augmenting A Zone's Hook
115115

116+
When you fork a zone, you'll often want to control how the parent zone's
117+
hook gets called.
118+
119+
Prefixing a hook with `$` means that the hook will be passed the
120+
parent zone's hook, and the hook will be expected to return the function to
121+
be invoked rather than be the function itself.
122+
116123
```javascript
117124
var someZone = zone.fork({
118125
onZoneLeave: function () {
@@ -121,8 +128,36 @@ var someZone = zone.fork({
121128
});
122129

123130
someZone.fork({
131+
$onZoneLeave: function (parentOnLeave) {
132+
// return the hook
133+
return function onZoneLeave() {
134+
parentOnLeave();
135+
console.log('cya l8r');
136+
};
137+
}
138+
}).run(function () {
139+
// do stuff
140+
});
141+
142+
// logs: goodbye
143+
// cya l8r
144+
```
145+
146+
#### `+` and `-` Sugar
147+
Most of the time, you'll want to run a hook before or after the parent's implementation.
148+
You can prefix a hook with `-` for running before, and `+` for running after.
149+
150+
The above can be written like this:
151+
152+
```javascript
153+
var someZone = zone.fork({
124154
onZoneLeave: function () {
125-
this.parent.onZoneLeave();
155+
console.log('goodbye');
156+
}
157+
});
158+
159+
someZone.fork({
160+
'+onZoneLeave': function (parentOnLeave) {
126161
console.log('cya l8r');
127162
}
128163
}).run(function () {
@@ -133,6 +168,8 @@ someZone.fork({
133168
// cya l8r
134169
```
135170

171+
This frees you from writing boilerplate to compose a new hook.
172+
136173
## API
137174

138175
Zone.js exports a single object: `window.zone`.
@@ -166,6 +203,10 @@ myZone.run(function () {
166203

167204
Below describes the behavior of each of these hooks.
168205

206+
### `zone.onZoneCreated`
207+
208+
Runs when a zone is forked.
209+
169210
### `zone.onZoneEnter`
170211

171212
Before a function invoked with `zone.run`, this hook runs.

counting-zone.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* See example/counting.html
3+
*/
4+
zone.countingZone = {
5+
'-onZoneCreated': function () {
6+
zone.countingZone.counter += 1;
7+
},
8+
'+onZoneLeave': function () {
9+
zone.countingZone.counter -= 1;
10+
if (zone.countingZone.counter === 0) {
11+
this.onFlush();
12+
}
13+
},
14+
reset: function () {
15+
zone.countingZone.counter = 0;
16+
},
17+
counter: function () {
18+
return zone.countingZone.counter;
19+
},
20+
onFlush: function () {}
21+
};

example/counting.html

Lines changed: 20 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<title>Counting Pending Tasks</title>
66
<link rel="stylesheet" href="style.css">
77
<script src="../zone.js"></script>
8-
<script src="../long-stack-trace-zone.js"></script>
8+
<script src="../counting-zone.js"></script>
99
</head>
1010
<body>
1111

@@ -26,59 +26,32 @@ <h1>Counting Pending Tasks</h1>
2626
/*
2727
* Zone that counts pending async tasks
2828
*/
29-
var countingZone = (function () {
30-
var count = 0,
31-
start;
32-
return {
33-
_wrap: function (fn) {
34-
return function () {
35-
var ret = fn.apply(this, arguments);
36-
count -= 1;
37-
zone._print();
38-
return ret;
39-
};
40-
},
41-
42-
_print: function () {
43-
output.innerHTML = 'pending task count: ' + count +
44-
(count === 0 ? (' DONE! ' + (Date.now() - start)/1000 + 's') : '');
45-
},
46-
47-
reset: function () {
48-
start = 0;
49-
},
50-
51-
run: function () {
52-
if (!start) {
53-
start = Date.now();
54-
}
55-
return zone.run.apply(this, arguments);
56-
},
57-
58-
59-
onError: function (e) {
60-
console.log(e.stack);
61-
},
62-
63-
setTimeout: function () {
64-
count += 1;
65-
zone._print();
66-
arguments[0] = zone._wrap(arguments[0]);
67-
return zone._setTimeout.apply(this, arguments);
68-
},
69-
70-
_setTimeout: zone.setTimeout
71-
};
72-
}());
73-
29+
var myCountingZone = zone.fork(zone.countingZone).fork({
30+
'+onZoneCreated': function () {
31+
zone.countingZone.start || (zone.countingZone.start = Date.now());
32+
this.print();
33+
},
34+
'-onZoneLeave': function (delegate) {
35+
this.print();
36+
},
37+
'+reset': function (delegate) {
38+
zone.countingZone.start = 0;
39+
},
40+
print: function () {
41+
counter = this.counter();
42+
output.innerHTML = counter ?
43+
'pending task count: ' + counter :
44+
' DONE! ' + (Date.now() - zone.countingZone.start)/1000 + 's';
45+
}
46+
});
7447

7548
/*
7649
* We want to profile just the actions that are a result of this button, so with
7750
* a single line of code, we can run `main` in the countingZone
7851
*/
7952

8053
b1.addEventListener('click', function () {
81-
zone.fork(countingZone).run(main);
54+
myCountingZone.run(main);
8255
});
8356

8457

test/zone.spec.js

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,7 @@ describe('Zone.patch', function () {
183183
expect(leaveSpy).toHaveBeenCalled();
184184
});
185185

186-
it('should throw if onError is not defined', function () {
187-
expect(function () {
188-
zone.run(throwError);
189-
}).toThrow();
190-
});
191-
192-
it('should fire onZoneCreeated when a zone is forked', function () {
186+
it('should fire onZoneCreated when a zone is forked', function () {
193187
var createdSpy = jasmine.createSpy();
194188
var counter = 0;
195189
var myZone = zone.fork({

zone.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,40 @@ function Zone(parentZone, data) {
77
zone.parent = parentZone;
88

99
Object.keys(data || {}).forEach(function(property) {
10-
zone[property] = data[property];
10+
11+
var _property = property.substr(1);
12+
13+
// augment the new zone with a hook decorates the parent's hook
14+
if (property[0] === '$') {
15+
zone[_property] = data[property](parentZone[_property] || function () {});
16+
17+
// augment the new zone with a hook that runs after the parent's hook
18+
} else if (property[0] === '+') {
19+
if (parentZone[_property]) {
20+
zone[_property] = function () {
21+
var result = parentZone[_property].apply(this, arguments);
22+
data[property].apply(this, arguments);
23+
return result;
24+
};
25+
} else {
26+
zone[_property] = data[property];
27+
}
28+
29+
// augment the new zone with a hook that runs before the parent's hook
30+
} else if (property[0] === '-') {
31+
if (parentZone[_property]) {
32+
zone[_property] = function () {
33+
data[property].apply(this, arguments);
34+
return parentZone[_property].apply(this, arguments);
35+
};
36+
} else {
37+
zone[_property] = data[property];
38+
}
39+
40+
// set the new zone's hook (replacing the parent zone's)
41+
} else {
42+
zone[property] = data[property];
43+
}
1144
});
1245

1346
return zone;

0 commit comments

Comments
 (0)