Skip to content

Commit 49c0829

Browse files
committed
Rearrange timer-counting example
1 parent 7df5df7 commit 49c0829

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

Zone Solutions.md

+23-23
Original file line numberDiff line numberDiff line change
@@ -141,29 +141,6 @@ There are many complex use cases around how to use zones in the context of sched
141141

142142
Our very specific use case here is to monitor the number of outstanding timer tasks, i.e. `setTimeout` and `setInterval`, scheduled within the current zone. When this number changes, we can notify the zone. This could be used by a UI framework to ensure that all timers that are spawned from within an event handler have completed their work, before the framework goes through the work of updating the DOM.
143143

144-
Our HostSetupZone definition is then:
145-
146-
1. Let _outstandingTimersChanged_ be ? GetV(_options_, `"outstandingTimersChanged"`).
147-
1. If _outstandingTimersChanged_ is not *undefined*, and IsCallable(_outstandingTimersChanged_) is **false**, throw a **TypeError** exception.
148-
1. Set the value of _zone_'s [[HostDefined]] internal slot to Record { [[OutstandingTimersChanged]]: _outstandingTimersChanged_, [[OutstandingTimersCount]]: 0 }.
149-
150-
We also define ChangeOutstandingTimersCount(_delta_) as follows:
151-
152-
1. Let _currentZone_ be the current Realm Record's [[CurrentZone]] field.
153-
1. Let _outstandingTimersChanged_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersChanged]] field.
154-
1. If _outstandingTimersChanged_ is **undefined**, return.
155-
1. Let _currentCount_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field.
156-
1. Set the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field to _currentCount_ + _delta_.
157-
1. Queue a microtask perform the following steps:
158-
1. Let _newCount_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field. (NOTE: this could have changed and might not be _currentCount_ + _delta_ anymore.)
159-
1. Invoke _outstandingTimersChanged_ with **undefined** this value and an arguments list containing the number _newCount_.
160-
161-
We then modify:
162-
163-
- `setTimeout` and `setInterval` to call ChangeOutstandingTimersCount(+1) on invocation
164-
- `setTimeout`'s queued task to to call ChangeOutstandingTimersCount(-1) once the task finishes
165-
- `clearTimeout` and `clearInterval to call ChangeOutstandingTimersCount(-1) when they actually clear a timer
166-
167144
As a rough example of how this might work, consider the following:
168145

169146
```js
@@ -204,3 +181,26 @@ framework.addEventListener(myButton, "click", () => {
204181
This code would ensure that `synchronizeModelsWithViews` only happens after 150 milliseconds have passed, i.e. after all asynchronous (timer-related) work spawned from the event handler has finished. The framework uses this as a sign that things have settled down enough that it's time to take the potentially-expensive step of serializing the model state to the DOM.
205182

206183
As noted, this is just an illustrative example. A more robust solution would need to account for more than just timers (more flexibility), and might be able to reduce the number of calls from the browser into framework code by e.g. calling back only when the count reaches zero (less power). But hopefully it gives you the idea!
184+
185+
Accomplishing this is not very difficult with zones. Our HostSetupZone definition is:
186+
187+
1. Let _outstandingTimersChanged_ be ? GetV(_options_, `"outstandingTimersChanged"`).
188+
1. If _outstandingTimersChanged_ is not *undefined*, and IsCallable(_outstandingTimersChanged_) is **false**, throw a **TypeError** exception.
189+
1. Set the value of _zone_'s [[HostDefined]] internal slot to Record { [[OutstandingTimersChanged]]: _outstandingTimersChanged_, [[OutstandingTimersCount]]: 0 }.
190+
191+
We also define ChangeOutstandingTimersCount(_delta_) as follows:
192+
193+
1. Let _currentZone_ be the current Realm Record's [[CurrentZone]] field.
194+
1. Let _outstandingTimersChanged_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersChanged]] field.
195+
1. If _outstandingTimersChanged_ is **undefined**, return.
196+
1. Let _currentCount_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field.
197+
1. Set the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field to _currentCount_ + _delta_.
198+
1. Queue a microtask perform the following steps:
199+
1. Let _newCount_ be the value of _currentZone_'s [[HostDefined]] internal slot's [[OutstandingTimersCount]] field. (NOTE: this could have changed and might not be _currentCount_ + _delta_ anymore.)
200+
1. Invoke _outstandingTimersChanged_ with **undefined** this value and an arguments list containing the number _newCount_.
201+
202+
We then modify:
203+
204+
- `setTimeout` and `setInterval` to call ChangeOutstandingTimersCount(+1) on invocation
205+
- `setTimeout`'s queued task to to call ChangeOutstandingTimersCount(-1) once the task finishes
206+
- `clearTimeout` and `clearInterval to call ChangeOutstandingTimersCount(-1) when they actually clear a timer

0 commit comments

Comments
 (0)