Subject loses observer from array after first value emitted. #7144
Unanswered
straiforos
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello!
I have been working with an Angular application where I route between a table and an edit form. I cache the route so my init lifecycles do not re-run.
In a data service, I have a subject that allows me to pass the value from the form and pass it to the table via a subscription. The first value comes through but when I inspect the observable source which is the subject, the subject loses the observer and detaches from the source leaving the second value emitted lost and not communicated to the observable that my component is listening to from the subject.
I have tried returning the subject directly and not using asObservable. I have used replay subjects and behavior subjects. The Subject and ReplaySubject seem to have the same behavior of emitting the first value and the observer in the source subject is not longer in the array making the observer unaware of the next values. My solution is a hack where on a lifecycle that runs often to call the method that returns the subject.asObservable() and the value comes in reattaching the observer to the source subject.
ReplaySubjects work as the Subject did so I do not need to re-emit values. BehaviorSubject works differently and never returns the first value which I find weird.
My StackOverflow question: https://stackoverflow.com/questions/75023743/subject-loses-observer-from-array-after-first-value-emission-angular-routereuse
Data Service for next and observe
`
private taskDetailViewSubject: Subject = new Subject();
`
OnInit Lifecycle code (moved to AfterViewCheck to force observation on the subject on route reattach)
this.getUpdatedRows = this.taskTableService.getTaskUpdated().pipe( map((task: Task) => this.taskTableService.getTaskRow(task)), filter((task: TaskRow) => !!task), tap((newRow) => this.updateRow(newRow, null)) ); this.getUpdatedRows.subscribe();
I have screenshots showing my sleuthing that indicates after first value emitted the observer is lost from the subject making the second value not come through:

My form pushes the saved value to the subject.next(value)
My component listening to the subject.asObservable() has a observer in its source:
After the value is passed and tap operations run in the component to update the row edited the observer in the source is lost:

The second value that is passed in the data service shows the subject directly (the source of the observable in the component) lost the observer:
My hack is the following:
ngAfterViewChecked(): void { this.getUpdatedRows = this.taskTableService.getTaskUpdated().pipe( takeUntil(this.destroySignal$), map((task: Task) => this.taskTableService.getTaskRow(task)), filter((task: TaskRow) => !!task), tap((newRow) => this.updateRow(newRow, null)) ); this.getUpdatedRows.subscribe(); }
That makes the component re-run
getTaskUpdated(): Observable<Task> { return this.taskDetailViewSubject.asObservable(); }
adding a new observer to the observers list allowing me to receive the second value. I am confident the routing caching does not unsubscribe the observable.
Beta Was this translation helpful? Give feedback.
All reactions