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
{{ message }}
Repository navigation
scan() operator unexpectedly resets or fails to accumulate emissions across multiple emissions #7540
When using the scan() operator in RxJS (version 7.8.1), the accumulator parameter (a) does not correctly retain previous values across emissions. Instead, it appears to be empty or reset with each new emission, even though the index parameter (i) increments as expected. This suggests that scan() is receiving consecutive emissions but failing to persist the accumulated state.
Expected behavior
The scan() operator should correctly accumulate all previous emissions.
The accumulator parameter (a) should contain the history of all prior emissions, growing over time.
import{ReplaySubject,scan,map,tap,Observable}from'rxjs';enumDashboardViews{expandedTabs='expandedTabs'}constviews$=newReplaySubject<DashboardViews[]>(1);constviewChange$: Observable<boolean>=views$.pipe(map(view=>({ view,time: newDate().valueOf()})),scan((a,c,i)=>{console.log('Index:',i);// Index increases correctlyconsole.log('Accumulator:',a);// Accumulator is unexpectedly empty on each emissiona.push(c);returna;},[]as{time: number,view: DashboardViews[]}[]),tap(v=>console.log('Accumulated values:',v)),map((views)=>{if(views.length<2)returnfalse;constcurr=views[views.length-1];constprev=views[views.length-2];returnprev.view.includes(DashboardViews.expandedTabs)!==curr.view.includes(DashboardViews.expandedTabs);}));// Simulate emissionsviews$.next([DashboardViews.expandedTabs]);views$.next([]);views$.next([DashboardViews.expandedTabs]);viewChange$.subscribe(v=>console.log('viewChange',v));
Reproduction URL
No response
Version
7.8.1
Environment
RxJS version: 7.81
Angular version: 18.2.1
Node.js version: 20.18.1
Browser: Chrome 133
OS: macOS 14.7.4 (23H420)
Additional context
The issue persists even when using shareReplay(), defer(), and ReplaySubject() with a larger buffer size, suggesting that this may be a bug in the scan() operator itself.
The i index increasing indicates that the emissions are consecutive, yet the accumulator does not persist previous values.
This behavior does not align with the expected behavior of scan() in RxJS.
Your reproduction does not seem to give the output you provided.
You may want to know that the output observable is cold and does not subscribe to the ReplaySubject until you call subscribe on it. So you are missing every emission prior to calling subscribe. After you subscribe to the output, only a single value from the ReplaySubject is replayed, and so nothing is emitted from the scan operator.
Moving subscribe before the view$.next calls makes this work as expected on 7.8.1
Suggest closing
Edit: keep in mind you are also mutating the accumulator array with push instead of copying it inside scan, so if you are retaining this array elsewhere in the program or mutating it further that is probably why you are seeing an empty array in your logs
Activity
macksal commentedon Apr 14, 2025
Your reproduction does not seem to give the output you provided.
You may want to know that the output observable is cold and does not subscribe to the ReplaySubject until you call subscribe on it. So you are missing every emission prior to calling subscribe. After you subscribe to the output, only a single value from the ReplaySubject is replayed, and so nothing is emitted from the scan operator.
Moving subscribe before the
view$.nextcalls makes this work as expected on 7.8.1Suggest closing
Edit: keep in mind you are also mutating the accumulator array with push instead of copying it inside scan, so if you are retaining this array elsewhere in the program or mutating it further that is probably why you are seeing an empty array in your logs