Let's assume we have an app where user has a calendar where he can select a date for which he wants to get list of events. When user selects the date, we add an event CalendarSelectedDateChanged(DateTime). Bloc component fetches data from API each time we receive such an event. We can imagine a situation when the response is received with different delay. This will produce the following scenario:
- User clicks date 1
- API call is made with param date=1
- State is set to loading
- User clicks date 2
- State is set to loading
- Response from request date=2 is received
- State is set to dataLoadSuccess(date=2)
Expected result is that we discard response from request date=1 here
- Response from request date=1 is received
- State is set to dataLoadSuccess(date=1)
How can we resolve such a race condition in the most elegant way (preferably for all BLoCs in the app at once)?
Here's an exemplary code that will produce such an issue:
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
ExampleBloc()
: super(ExampleDataLoadInProgress(DateTime.now())) {
on<ExampleSelectedDateChanged>((event, emit) async {
await _fetchData(event.date, emit);
});
}
Future<void> _fetchData(DateTime selectedDate,
Emitter<ExampleState> emit,) async {
emit(ExampleDataLoadInProgress(selectedDateTime));
try {
final data = callAPI(selectedDateTime);
emit(ExampleDataLoadSuccess(data, selectedDate));
} on ApiException catch (e) {
emit(ExampleDataLoadFailure(e, selectedDateTime));
}
}
}