[英]Flutter BLoC event race condition
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)
.当用户选择日期时,我们添加一个事件
CalendarSelectedDateChanged(DateTime)
。 Bloc component fetches data from API each time we receive such an event.每次我们收到这样的事件时,Bloc 组件都会从 API 获取数据。 We can imagine a situation when the response is received with different delay.
我们可以想象以不同的延迟接收响应的情况。 This will produce the following scenario:
这将产生以下场景:
Expected result is that we discard response from request date=1 here预期结果是我们在这里丢弃来自请求日期=1 的响应
How can we resolve such a race condition in the most elegant way (preferably for all BLoCs in the app at once)?我们如何以最优雅的方式解决这种竞争条件(最好同时解决应用程序中的所有 BLoC)?
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));
}
}
}
By default all events are processed concurrently, you can change that behavior by setting a custom transformer:默认情况下,所有事件都是并发处理的,您可以通过设置自定义转换器来更改该行为:
You can read more about transformers here: https://pub.dev/packages/bloc_concurrency您可以在此处阅读有关转换器的更多信息: https : //pub.dev/packages/bloc_concurrency
class ExampleBloc extends Bloc<ExampleEvent, ExampleState> {
ExampleBloc()
: super(ExampleDataLoadInProgress(DateTime.now())) {
on<ExampleSelectedDateChanged>((event, emit) async {
await _fetchData(event.date, emit);
},
transformer: restartable(), // ADD THIS LINE
);
}
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));
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.