-
-
Notifications
You must be signed in to change notification settings - Fork 3.4k
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: Bloc Concurrency with restartable transformer does not cancel previous event #3349
Comments
Hi @PhilipPurwoko 👋 Are you able to provide a minimal reproduction sample? Thanks 🙏 |
Hi @felangel ! void handleEvent() async {
void onDone() {
emitter.complete();
_emitters.remove(emitter);
if (!controller.isClosed) controller.close();
}
try {
_emitters.add(emitter);
await handler(event as E, emitter);
} catch (error, stackTrace) {
onError(error, stackTrace);
rethrow;
} finally {
onDone();
}
} Execution of Minimal code to reproduce issue: class TestEvent {}
class TestBloc extends Bloc<TestEvent, Object> {
TestBloc() : super(Object()) {
on<TestEvent>(_onTestEvent, transformer: restartable());
}
var testCounter = 0;
Future<void> _onTestEvent(event, emit) async {
final counter = testCounter++;
print('Starting test count: $counter, is emitter alive: ${!emit.isDone}');
await Future.delayed(const Duration(seconds: 5));
// We should reach here only for latest event
print('Finished test count: $counter, is emitter alive: ${!emit.isDone}');
}
}
void main() {
final bloc = TestBloc();
bloc.listen(null);
bloc.add(TestEvent());
bloc.add(TestEvent());
bloc.add(TestEvent());
}
// Expected to print:
// Starting test count: 0, is emitter alive: true
// Starting test count: 1, is emitter alive: true
// Starting test count: 2, is emitter alive: true
// Finished test count: 2, is emitter alive: true
// Actually prints:
// Starting test count: 0, is emitter alive: true
// Starting test count: 1, is emitter alive: true
// Starting test count: 2, is emitter alive: true
// Finished test count: 0, is emitter alive: false
// Finished test count: 1, is emitter alive: false
// Finished test count: 2, is emitter alive: true |
The fix would be to save |
Hi @YStepiuk import 'package:bloc/bloc.dart';
import 'package:bloc_concurrency/bloc_concurrency.dart';
class TestEvent {}
class TestBloc extends Bloc<TestEvent, Object> {
TestBloc() : super(Object()) {
on<TestEvent>(_onTestEvent, transformer: restartable());
}
var testCounter = 0;
Future<void> _onTestEvent(event, emit) async {
final counter = testCounter++;
print('Starting test count: $counter, is emitter alive: ${!emit.isDone}');
await Future.delayed(const Duration(seconds: 5));
if (emit.isDone) return;
// We should reach here only for latest event
print('Finished test count: $counter, is emitter alive: ${!emit.isDone}');
}
}
void main() {
final bloc = TestBloc();
bloc.stream.listen(null);
bloc.add(TestEvent());
bloc.add(TestEvent());
bloc.add(TestEvent());
}
// Actually prints:
// Starting test count: 0, is emitter alive: true
// Starting test count: 1, is emitter alive: true
// Starting test count: 2, is emitter alive: true
// Finished test count: 2, is emitter alive: true This is also related to #3069 |
Closing for now since there don't appear to be any actionable next steps -- this is working as expected. Feel free to comment with any outstanding questions and I'm happy to continue the conversation 👍 |
Hello @felangel! |
Thanks for the kind words! The advantage of using restartable is you can disregard the results of previous events. This is important when you don't have expensive operations and you want the user to always see the results of their most recent actions. Hope that helps 👍 |
Hi @felangel |
Im trying to implement the approach from this article |
Description
Bloc Concurrency with restartable transformer does not cancel previous event
Steps To Reproduce
The bloc file
merchant_product_bloc.dart
that listen on an eventMerchantProductCartChanged
and emit the stateMerchantProductCartChange
The button I used to trigger the event
MerchantProductCartChanged
When I pressed the button 4 times very fast. It logs 4 times as well and call API 4 times
Expected Behavior
Should only logs one line at last event
The text was updated successfully, but these errors were encountered: