-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
First operator is not completing the observable. #1759
Comments
To add some detail: The call to the BehaviorSubject.next inside of the subscribe method seems to be the issue. Since first() calls complete after emitting the value in the _emitValue function, calling next on the behavior subject synchronously will cause an infinite loop. This doesn't occur with take() since the recursive call will complete when the number of emitted items is greater than the count. If you make the "next" call async, then the first operator behaves correctly.
|
It's worth nothing that you are not allowed to call |
@onlyann yup, that's a bug. It appears to be an issue with the synchronous nexting inside of the observation. Here's a more minimal example showing the bug: var store$ = new Rx.Subject();
store$.first().subscribe((x) => {
console.log("I have been called " + x);
store$.next({a: x[0] + 1, b: x[1] + 1});
});
store$.next({ a: 1, b: 2 }) But if you use a var store$ = new Rx.Subject();
store$.first().subscribe((x) => {
console.log("I have been called " + x);
setTimeout(() => store$.next({a: x[0] + 1, b: x[1] + 1}));
});
store$.next({ a: 1, b: 2 }) |
Is it expected to allow to source emitting value in subscription in case of synchronous observable instead of should be scheduled differently? (just fyi - this does occur same on v4) |
Since it doesn't complete, it holds on to the observers and can cause memory leaks: In both cases, wrapping the var store$ = new Rx.Subject();
store$.take(1).subscribe((x) => {
console.log("I have been called " + x.a);
store$.next({a: x[0] + 1, b: x[1] + 1});
}, () => {}, () => console.log("completed"));
store$.next({ a: 1, b: 2 })
// "I have been called 1" var store$ = new Rx.Subject();
store$.take(1).subscribe((x) => {
console.log("I have been called " + x.a);
setTimeout(() => store$.next({a: x[0] + 1, b: x[1] + 1}));
}, () => {}, () => console.log("completed"));
store$.next({ a: 1, b: 2 })
// "I have been called 1"
// "completed" |
Protecting against re-entrency without throwing errors or dropping values would necessitate introducing unbounded buffers, which was a conscious design trade-off we made in the early days. In this case, the This isn't a bug in As demonstrated, introducing an asynchronous boundary between emission and consumption (or vice-versa) is the best alternative here, though it doesn't have to be async across tick boundaries; async on the asap scheduler (which still blocks the current event loop) does the trick: console.clear();
setTimeout(() => console.log('setTimeout flushed'));
var store$ = new Rx.Subject();
store$.take(1)
.observeOn(Rx.Scheduler.asap)
.subscribe((x) => {
console.log("I have been called " + x.a);
store$.next({a: x[0] + 1, b: x[1] + 1});
}, () => {}, () => console.log("completed"));
store$.next({ a: 1, b: 2 });
// "I have been called 1"
// "completed"
Rx.Scheduler.asap.schedule(() => console.log('asap flushed'));
// "asap flushed"
// "setTimeout flushed" |
@trxcllnt is correct. It's the reentrancy protection that is causing this effect. I think we can close this issue for now, however, it might be worth discussing the merits of the reentrancy protections in Subjects, as I know that we've discussed it in the past, but it can't hurt to revisit. |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
**RxJS version: 5.0.0-beta.6
**Code to reproduce:
http://codepen.io/anon/pen/zBrPzj?editors=1111
Expected behavior:
Subcribe should only be called once when using the
first
operator.Actual behavior:
It doesn't complete the subscription.
Additional information
Replacing
first
withtake(1)
works as expected.The text was updated successfully, but these errors were encountered: