11/* 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" ;
38import {
49 Observable ,
510 Operator ,
@@ -48,17 +53,16 @@ export class ɵZoneScheduler implements SchedulerLike {
4853}
4954
5055class 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+ ) { }
5560
5661 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 ) ;
6266
6367 return source
6468 . pipe (
@@ -71,17 +75,6 @@ class BlockUntilFirstOperator<T> implements Operator<T, T> {
7175 . subscribe ( subscriber )
7276 . add ( unscheduleTask ) ;
7377 }
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- }
8578}
8679
8780@Injectable ( {
@@ -90,6 +83,7 @@ class BlockUntilFirstOperator<T> implements Operator<T, T> {
9083export class ɵAngularFireSchedulers {
9184 public readonly outsideAngular : ɵZoneScheduler ;
9285 public readonly insideAngular : ɵZoneScheduler ;
86+ public readonly pendingTasks = inject ( ExperimentalPendingTasks ) ;
9387
9488 constructor ( public ngZone : NgZone ) {
9589 // @ts -ignore
@@ -149,7 +143,9 @@ export function ɵkeepUnstableUntilFirstFactory(
149143 return function keepUnstableUntilFirst < T > (
150144 obs$ : Observable < T >
151145 ) : Observable < T > {
152- obs$ = obs$ . lift ( new BlockUntilFirstOperator ( schedulers . ngZone ) ) ;
146+ obs$ = obs$ . lift (
147+ new BlockUntilFirstOperator ( schedulers . ngZone , schedulers . pendingTasks )
148+ ) ;
153149
154150 return obs$ . pipe (
155151 // 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(
165161// @ts -ignore
166162const zoneWrapFn = (
167163 it : ( ...args : any [ ] ) => any ,
168- macrotask : MacroTask | undefined
164+ taskDone : VoidFunction | undefined
169165) => {
170166 // eslint-disable-next-line @typescript-eslint/no-this-alias
171167 const _this = this ;
172168 // function() is needed for the arguments object
173169 return function ( ) {
174170 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 ) ;
181173 }
182174 return run ( ( ) => it . apply ( _this , _arguments ) ) ;
183175 } ;
@@ -187,26 +179,18 @@ export const ɵzoneWrap = <T = unknown>(it: T, blockUntilFirst: boolean): T => {
187179 // function() is needed for the arguments object
188180 return function ( ) {
189181 // @ts -ignore
190- let macrotask : MacroTask | undefined ;
182+ let taskDone : VoidFunction | undefined ;
191183 const _arguments = arguments ;
192- // if this is a callback function, e.g, onSnapshot, we should create a microtask and invoke it
184+ // if this is a callback function, e.g, onSnapshot, we should create a pending task and complete it
193185 // only once one of the callback functions is tripped.
194186 for ( let i = 0 ; i < arguments . length ; i ++ ) {
195187 if ( typeof _arguments [ i ] === "function" ) {
196188 if ( blockUntilFirst ) {
197189 // @ts -ignore
198- macrotask ||= run ( ( ) =>
199- Zone . current . scheduleMacroTask (
200- "firebaseZoneBlock" ,
201- noop ,
202- { } ,
203- noop ,
204- noop
205- )
206- ) ;
190+ taskDone ||= run ( ( ) => getSchedulers ( ) . pendingTasks . add ( ) ) ;
207191 }
208192 // TODO create a microtask to track callback functions
209- _arguments [ i ] = zoneWrapFn ( _arguments [ i ] , macrotask ) ;
193+ _arguments [ i ] = zoneWrapFn ( _arguments [ i ] , taskDone ) ;
210194 }
211195 }
212196 const ret = runOutsideAngular ( ( ) => ( it as any ) . apply ( this , _arguments ) ) ;
@@ -234,15 +218,11 @@ export const ɵzoneWrap = <T = unknown>(it: T, blockUntilFirst: boolean): T => {
234218 )
235219 )
236220 ) ;
237- } else if ( typeof ret === "function" && macrotask ) {
221+ } else if ( typeof ret === "function" && taskDone ) {
238222 // Handle unsubscribe
239223 // function() is needed for the arguments object
240224 return function ( ) {
241- setTimeout ( ( ) => {
242- if ( macrotask && macrotask . state === "scheduled" ) {
243- macrotask . invoke ( ) ;
244- }
245- } , 10 ) ;
225+ setTimeout ( taskDone , 10 ) ;
246226 return ret . apply ( this , arguments ) ;
247227 } ;
248228 } else {
0 commit comments