Repository navigation
feat(zones)!: deliver Observable read values as microtasks - #3833
Open
armando-navarro wants to merge 1 commit into
Open
armando-navarro wants to merge 1 commit into
armando-navarro wants to merge 1 commit into
Conversation
The insideAngular scheduler was built over asyncScheduler, so every value from an Observable read reached its subscriber one setInterval turn after Firebase handed it over. A private AsapScheduler instance delivers at the next microtask checkpoint instead, still never synchronously. It is private because rxjs's shared asapScheduler cancels the rest of a batch when one action throws. Measured on Angular 22.2 apps, zone.js and zoneless: delivery moves ahead of a zero-delay timer in every run, change detection and ordering are unchanged, and a server render reports stable about a millisecond sooner. The compat AngularFireAuth streams move too. BREAKING CHANGE: Observable reads (collectionData, docData, authState, user, objectVal, listVal and the rest) now deliver at the next microtask checkpoint instead of after a zero-delay timer. A test that waits only for microtasks now sees a value whose source emits in a microtask. Code that orders its own setTimeout against a read's value sees the timer run after the value, not before. In a zoneless server render, a value arriving between stability and serialization reaches a hand-written TransferState entry but not the HTML. Fixes angular#3832
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checklist
yarn install,yarn testrun successfully? yes, asnpm ciandnpm testDescription
Builds the
insideAngularscheduler insrc/zones.tsover a privateAsapSchedulerinstance instead of rxjs'sasyncScheduler, so every value from an Observable-returning read reaches the subscriber at the next microtask checkpoint instead of after asetIntervalturn.asapSchedulerbecause the shared one runs every action scheduled in a turn as one batch and cancels the rest of the batch when one action throws, which would let another library's action drop a delivery.AsapSchedulerandAsapActioncome fromrxjs/internal/scheduler/, a path rxjs 7.8 lists in itsexportsmap but keeps underinternal.What this grants, measured on Angular 22.2 zone.js and zoneless apps, before and after:
collectionDataagainst the Firestore emulator and the compatauthStateagainst the Auth emulator in Chrome.What does not change:
What upgrading apps may notice:
fakeAsyncwithflushMicrotasks()alone) now sees a value whose source emits in a microtask, as Auth and a promise-based mock do. Firestore hands its snapshots over in asetTimeout, so Firestore reads still need a timer to advance. Tests that advance timers are unchanged.setTimeoutwhen a read emits sees that timer run after the value arrives, not before.TransferStateentry but not the HTML, because the zoneless change-detection pass is itself a later timer. Before this change such a value reached neither.AngularFireAuthstreams move with the modular reads. CompatAngularFireFunctionsandAngularFireMessagingonly hand over their SDK instance through this scheduler, and compat Database and Firestore do not use it.Verification:
src/zones.spec.ts: a wrapped Observable's value arrives asynchronously, inside the Angular zone, and before a zero-delay timer registered when the source emitted, and the delivery scheduler is anAsapSchedulerthat is not rxjs's shared instance. Fails onmain, passes here.npm run lint,npm run test:node,npm run test:chrome-headlessandnpm run test:firefox-headlesspass on the branch.