Skip to content
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

fix(buffer): emit last buffer if source completes #2174

Merged
merged 1 commit into from
Jan 31, 2017

Conversation

JaminFarr
Copy link

Description:
This fixes an issue with the bufffer operator.
If the source emits values and completes before the notifier emits, those values are lost.

source  = --a--b--c--d--e--|
notifer = ----x-----x-------
source.buffer(notifer)

results
[a]
[b, c]

d & e are never emitted

Related issue: #2154

Fix buffer operator not emitting the last buffer when the source
completes. This is closer to rxjs v4* behaviour and matches the
behaviour of the other buffer operators. The _complete method is very
similar to thoses in bufferCount, bufferTime and bufferWhen.

*rxjs v4 will always emit the buffer if the source completes even if the
buffer is empty. This fix only emits if the buffer is non empty.

BREAKING CHANGE:

extra value may be emitted when source completes

@coveralls
Copy link

coveralls commented Dec 7, 2016

Coverage Status

Coverage increased (+0.002%) to 97.688% when pulling 25307d0 on JaminFarr:fix-buffer-last-array-missing into 89b506d on ReactiveX:master.

@mpodlasin
Copy link
Contributor

mpodlasin commented Dec 16, 2016

@JaminFarr does in this branch last buffer is emited also when notifier observable completes? (for context see: #1754)

@benlesh
Copy link
Member

benlesh commented Dec 17, 2016

We'll need to verify that this is how Rx4 behaved. As it stands right now this would be more of a breaking change than a "fix", I think. But if it behaved this way in Rx4, there's an argument to be made that this is a fix.

@benlesh
Copy link
Member

benlesh commented Dec 17, 2016

@JaminFarr confirmed that Rx4 behaves this way and Rx5 does not... therefor this is a bug fix. 👍

@benlesh benlesh added the bug Confirmed bug label Dec 17, 2016
@benlesh
Copy link
Member

benlesh commented Dec 17, 2016

This LGTM... Will merge after conferring with others. Pretty sure this should land in 5.0.2 as a bug fix though.

@JaminFarr
Copy link
Author

@Podlas29 No, This PR only changes the source complete behavior.

Examples from #1754

Observable.never().buffer(Observable.empty());

// Result: Same, emits nothing. Source never completes so it is not affected by this fix. 
const source = Observable.from([1,2,3,4,5,6]);
source.buffer(source.take(2));

// Result:
[] // Same
[] // Same
[1, 2, 3, 4, 5, 6] // new from this change
// The notifier emits twice and completes before source is subscribed to, producing
// the first two empty array results. Then the source completes and the array of the
// remaining values is emitted.

@Blesh Great.

Fix buffer operator not emitting the last buffer when the source
completes. This is closer to rxjs v4* behaviour and matches the
behaviour of the other buffer operators. The _complete method is very
similar to thoses in bufferCount, bufferTime and bufferWhen.

*rxjs v4 will always emit the buffer if the source completes even if the
buffer is empty. This fix only emits if the buffer is non empty.

BREAKING CHANGE:

The `buffer()` operator now emits what's partially buffered when the
source completes. This is closer to rxjs v4* behaviour and matches the
v5 behaviour of the other buffer operators.
@jayphelps jayphelps force-pushed the fix-buffer-last-array-missing branch from 25307d0 to 6405cf4 Compare January 31, 2017 03:15
@jayphelps jayphelps merged commit 30b1436 into ReactiveX:next Jan 31, 2017
@jayphelps
Copy link
Member

Merged into next branch, as we decided in our core team meeting today this was indeed a breaking change that has to go into a major version bump.

@jayphelps
Copy link
Member

Thanks @JaminFarr !!

@Jason3S
Copy link

Jason3S commented Feb 12, 2017

@JaminFarr What is the behavior of this fix? Does it emit immediately or wait until the closingNotifier. Please see #2361

@JaminFarr
Copy link
Author

JaminFarr commented Feb 12, 2017

@Jason3S This fix emits immediately when the source completes with the remaining values. This matches RxJS4 but looks like the opposite behavior to what you're after. I don't think there is a version of BufferWhen in RxJS4 to compare against.

As a workaround to delay the last buffer value to emit in time with the trigger, you can zip the result with the trigger.

const Observable = Rx.Observable;

const source$ = Observable.interval(200).take(25)
const trigger$ = Observable.interval(2000).share()

// I'm using window and mergeMap as a workaround until this PR is merged.
// This is the same as .buffer(trigger$) post fix.
source$
  .window(trigger$)
  .mergeMap(x => x.toArray())

// Use zip to delay the last value and a selector to remove the trigger value.
  .zip(trigger$, (sourceValue /*, triggerValue*/) => sourceValue)

  .subscribe(x => console.log(x))

/*
2s: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4s: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
6s: [20, 21, 22, 23, 24] -- without the zip this will emit at ~5s.
*/

@Jason3S
Copy link

Jason3S commented Feb 12, 2017

Nice workaround.

@lock
Copy link

lock bot commented Jun 6, 2018

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.

@lock lock bot locked as resolved and limited conversation to collaborators Jun 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Confirmed bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants