| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,5 +1,10 @@ | |||
| 1 | 1 | /* eslint-disable @typescript-eslint/ban-ts-comment */ | |
| 2 | - import { Injectable, NgZone } from "@angular/core"; | ||
| 2 | + import { | ||
| 3 | + ExperimentalPendingTasks, | ||
| 4 | + Injectable, | ||
| 5 | + NgZone, | ||
| 6 | + inject, | ||
| 7 | + } from "@angular/core"; | ||
| 3 | 8 | import { | |
| 4 | 9 | Observable, | |
| 5 | 10 | Operator, | |
@@ -48,17 +53,16 @@ export class ɵZoneScheduler implements SchedulerLike { | |||
| 48 | 53 | } | |
| 49 | 54 | ||
| 50 | 55 | class BlockUntilFirstOperator<T> implements Operator<T, T> { | |
| 51 | - // @ts-ignore | ||
| 52 | - private task: MacroTask | null = null; | ||
| 53 | - | ||
| 54 | - constructor(private zone: any) {} | ||
| 56 | + constructor( | ||
| 57 | + private zone: any, | ||
| 58 | + private pendingTasks: ExperimentalPendingTasks | ||
| 59 | + ) {} | ||
| 55 | 60 | ||
| 56 | 61 | call(subscriber: Subscriber<T>, source: Observable<T>): TeardownLogic { | |
| 57 | - const unscheduleTask = this.unscheduleTask.bind(this); | ||
| 58 | - // @ts-ignore | ||
| 59 | - this.task = this.zone.run(() => | ||
| 60 | - Zone.current.scheduleMacroTask("firebaseZoneBlock", noop, {}, noop, noop) | ||
| 61 | - ); | ||
| 62 | + const taskDone = this.zone.run(() => this.pendingTasks.add()); | ||
| 63 | + // maybe this is a race condition, invoke in a timeout | ||
| 64 | + // hold for 10ms while I try to figure out what is going on | ||
| 65 | + const unscheduleTask = () => setTimeout(taskDone, 10); | ||
| 62 | 66 | ||
| 63 | 67 | return source | |
| 64 | 68 | .pipe( | |
@@ -71,17 +75,6 @@ class BlockUntilFirstOperator<T> implements Operator<T, T> { | |||
| 71 | 75 | .subscribe(subscriber) | |
| 72 | 76 | .add(unscheduleTask); | |
| 73 | 77 | } | |
| 74 | - | ||
| 75 | - private unscheduleTask() { | ||
| 76 | - // maybe this is a race condition, invoke in a timeout | ||
| 77 | - // hold for 10ms while I try to figure out what is going on | ||
| 78 | - setTimeout(() => { | ||
| 79 | - if (this.task != null && this.task.state === "scheduled") { | ||
| 80 | - this.task.invoke(); | ||
| 81 | - this.task = null; | ||
| 82 | - } | ||
| 83 | - }, 10); | ||
| 84 | - } | ||
| 85 | 78 | } | |
| 86 | 79 | ||
| 87 | 80 | @Injectable({ | |
@@ -90,14 +83,15 @@ class BlockUntilFirstOperator<T> implements Operator<T, T> { | |||
| 90 | 83 | export class ɵAngularFireSchedulers { | |
| 91 | 84 | public readonly outsideAngular: ɵZoneScheduler; | |
| 92 | 85 | public readonly insideAngular: ɵZoneScheduler; | |
| 86 | + public readonly pendingTasks = inject(ExperimentalPendingTasks); | ||
| 93 | 87 | ||
| 94 | 88 | constructor(public ngZone: NgZone) { | |
| 95 | - // @ts-ignore | ||
| 96 | 89 | this.outsideAngular = ngZone.runOutsideAngular( | |
| 90 | + // @ts-ignore | ||
| 97 | 91 | () => new ɵZoneScheduler(Zone.current) | |
| 98 | 92 | ); | |
| 99 | - // @ts-ignore | ||
| 100 | 93 | this.insideAngular = ngZone.run( | |
| 94 | + // @ts-ignore | ||
| 101 | 95 | () => new ɵZoneScheduler(Zone.current, asyncScheduler) | |
| 102 | 96 | ); | |
| 103 | 97 | globalThis.ɵAngularFireScheduler ||= this; | |
@@ -149,7 +143,9 @@ export function ɵkeepUnstableUntilFirstFactory( | |||
| 149 | 143 | return function keepUnstableUntilFirst<T>( | |
| 150 | 144 | obs$: Observable<T> | |
| 151 | 145 | ): Observable<T> { | |
| 152 | - obs$ = obs$.lift(new BlockUntilFirstOperator(schedulers.ngZone)); | ||
| 146 | + obs$ = obs$.lift( | ||
| 147 | + new BlockUntilFirstOperator(schedulers.ngZone, schedulers.pendingTasks) | ||
| 148 | + ); | ||
| 153 | 149 | ||
| 154 | 150 | return obs$.pipe( | |
| 155 | 151 | // Run the subscribe body outside of Angular (e.g. calling Firebase SDK to add a listener to a change event) | |
@@ -165,19 +161,15 @@ export function ɵkeepUnstableUntilFirstFactory( | |||
| 165 | 161 | // @ts-ignore | |
| 166 | 162 | const zoneWrapFn = ( | |
| 167 | 163 | it: (...args: any[]) => any, | |
| 168 | - macrotask: MacroTask | undefined | ||
| 164 | + taskDone: VoidFunction | undefined | ||
| 169 | 165 | ) => { | |
| 170 | 166 | // eslint-disable-next-line @typescript-eslint/no-this-alias | |
| 171 | 167 | const _this = this; | |
| 172 | 168 | // function() is needed for the arguments object | |
| 173 | 169 | return function () { | |
| 174 | 170 | const _arguments = arguments; | |
| 175 | - if (macrotask) { | ||
| 176 | - setTimeout(() => { | ||
| 177 | - if (macrotask.state === "scheduled") { | ||
| 178 | - macrotask.invoke(); | ||
| 179 | - } | ||
| 180 | - }, 10); | ||
| 171 | + if (taskDone) { | ||
| 172 | + setTimeout(taskDone, 10); | ||
| 181 | 173 | } | |
| 182 | 174 | return run(() => it.apply(_this, _arguments)); | |
| 183 | 175 | }; | |
@@ -186,27 +178,17 @@ const zoneWrapFn = ( | |||
| 186 | 178 | export const ɵzoneWrap = <T = unknown>(it: T, blockUntilFirst: boolean): T => { | |
| 187 | 179 | // function() is needed for the arguments object | |
| 188 | 180 | return function () { | |
| 189 | - // @ts-ignore | ||
| 190 | - let macrotask: MacroTask | undefined; | ||
| 181 | + let taskDone: VoidFunction | undefined; | ||
| 191 | 182 | const _arguments = arguments; | |
| 192 | - // if this is a callback function, e.g, onSnapshot, we should create a microtask and invoke it | ||
| 183 | + // if this is a callback function, e.g, onSnapshot, we should create a pending task and complete it | ||
| 193 | 184 | // only once one of the callback functions is tripped. | |
| 194 | 185 | for (let i = 0; i < arguments.length; i++) { | |
| 195 | 186 | if (typeof _arguments[i] === "function") { | |
| 196 | 187 | if (blockUntilFirst) { | |
| 197 | - // @ts-ignore | ||
| 198 | - macrotask ||= run(() => | ||
| 199 | - Zone.current.scheduleMacroTask( | ||
| 200 | - "firebaseZoneBlock", | ||
| 201 | - noop, | ||
| 202 | - {}, | ||
| 203 | - noop, | ||
| 204 | - noop | ||
| 205 | - ) | ||
| 206 | - ); | ||
| 188 | + taskDone ||= run(() => getSchedulers().pendingTasks.add()); | ||
| 207 | 189 | } | |
| 208 | 190 | // TODO create a microtask to track callback functions | |
| 209 | - _arguments[i] = zoneWrapFn(_arguments[i], macrotask); | ||
| 191 | + _arguments[i] = zoneWrapFn(_arguments[i], taskDone); | ||
| 210 | 192 | } | |
| 211 | 193 | } | |
| 212 | 194 | const ret = runOutsideAngular(() => (it as any).apply(this, _arguments)); | |
@@ -234,15 +216,11 @@ export const ɵzoneWrap = <T = unknown>(it: T, blockUntilFirst: boolean): T => { | |||
| 234 | 216 | ) | |
| 235 | 217 | ) | |
| 236 | 218 | ); | |
| 237 | - } else if (typeof ret === "function" && macrotask) { | ||
| 219 | + } else if (typeof ret === "function" && taskDone) { | ||
| 238 | 220 | // Handle unsubscribe | |
| 239 | 221 | // function() is needed for the arguments object | |
| 240 | 222 | return function () { | |
| 241 | - setTimeout(() => { | ||
| 242 | - if (macrotask && macrotask.state === "scheduled") { | ||
| 243 | - macrotask.invoke(); | ||
| 244 | - } | ||
| 245 | - }, 10); | ||
| 223 | + setTimeout(taskDone, 10); | ||
| 246 | 224 | return ret.apply(this, arguments); | |
| 247 | 225 | }; | |
| 248 | 226 | } else { | |
| Back | FazBrowse Home | New Git URL |
0 commit comments