Pewarta Proxy

📋 Server Request & Proxy Logs

Loading active proxy settings...
Developed by Khairul Adha (adhexa.id)
Mengambil log server...

⚙️ Pengaturan Proxy Target

Skip to content

feat(zones)!: deliver Observable read values as microtasks - #3833

Open
armando-navarro wants to merge 1 commit into
angular:mainfrom
armando-navarro:a41-microtask-delivery
Open

armando-navarro wants to merge 1 commit into
angular:mainfrom
armando-navarro:a41-microtask-delivery

Conversation

@armando-navarro

Copy link
Copy Markdown
Collaborator

Checklist

Description

Builds the insideAngular scheduler in src/zones.ts over a private AsapScheduler instance instead of rxjs's asyncScheduler, so every value from an Observable-returning read reaches the subscriber at the next microtask checkpoint instead of after a setInterval turn.

  • The instance is AngularFire's own rather than rxjs's shared asapScheduler because 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.
  • AsapScheduler and AsapAction come from rxjs/internal/scheduler/, a path rxjs 7.8 lists in its exports map but keeps under internal.
  • Nothing else in the wrapper changes: Promise-returning and callback-taking wrappers never used this scheduler.

What this grants, measured on Angular 22.2 zone.js and zoneless apps, before and after:

  • Values arrive before a zero-delay timer registered when the source emitted, in every run: a synthetic source in Chrome and Firefox, and collectionData against the Firestore emulator and the compat authState against the Auth emulator in Chrome.
  • A server render reports stable about 1 ms sooner after Firestore's last callback.

What does not change:

  • The DOM updates on delivery and the subscriber runs inside the Angular zone.
  • zone.js ticks once per value and zoneless once per burst.
  • Order is preserved.

What upgrading apps may notice:

  • A test that waits only for microtasks (a few awaited promises, vitest fake timers without advancing, fakeAsync with flushMicrotasks() 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 a setTimeout, so Firestore reads still need a timer to advance. Tests that advance timers are unchanged.
  • Code that registers its own setTimeout when a read emits sees that timer run after the value arrives, not before.
  • In a zoneless server render, a value arriving between the app reporting stable and serialization now reaches a hand-written TransferState entry but not the HTML, because the zoneless change-detection pass is itself a later timer. Before this change such a value reached neither.
  • The compat AngularFireAuth streams move with the modular reads. Compat AngularFireFunctions and AngularFireMessaging only hand over their SDK instance through this scheduler, and compat Database and Firestore do not use it.

Verification:

  • New spec 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 an AsapScheduler that is not rxjs's shared instance. Fails on main, passes here.
  • npm run lint, npm run test:node, npm run test:chrome-headless and npm run test:firefox-headless pass on the branch.

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
@armando-navarro armando-navarro added breaking change Upgrading apps must change something. Call it out in the release notes bump: major Size of the change: breaking, ships only in a major release comp: compat Compatibility layer for the pre-modular API (src/compat). comp: ssr Server-side rendering, hydration, @angular/ssr interop. comp: zones Change detection / zone.js / zoneless. type: feature New capability or enhancement. labels Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Upgrading apps must change something. Call it out in the release notes bump: major Size of the change: breaking, ships only in a major release comp: compat Compatibility layer for the pre-modular API (src/compat). comp: ssr Server-side rendering, hydration, @angular/ssr interop. comp: zones Change detection / zone.js / zoneless. type: feature New capability or enhancement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant