You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: Zone Solutions.md
+23-23
Original file line number
Diff line number
Diff line change
@@ -141,29 +141,6 @@ There are many complex use cases around how to use zones in the context of sched
141
141
142
142
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.
143
143
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
-
167
144
As a rough example of how this might work, consider the following:
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.
205
182
206
183
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