민프
[Flutter-Error] Dart에서 Future 취소하는 방법(CancelableOperation) 본문
Frontend/[Flutter Error]
[Flutter-Error] Dart에서 Future 취소하는 방법(CancelableOperation)
민프야 2025. 3. 20. 19:00이번 포스팅에서는 비동기 작업을 중간에 취소하는 방법 중 하나인 CancelableOperation을 소개하려고 합니다. 특히 BLoC(Cubit) 패턴에서 비동기 작업이 중첩되거나 화면 전환 시 작업이 취소되지 않아 발생하는 문제를 해결할 수 있는 좋은 방법입니다.
문제상황
Exception has occurred. StateError (Bad state: Cannot emit new states after calling close)
최근에 HomeCubit에서 게시글 목록을 불러오는 작업을 하던 중, 화면을 빠르게 이동하거나 여러 번 loadPosts()를 호출하면 이전 요청이 취소되지 않고 계속 실행되는 문제를 발견했습니다. 이 문제를 해결하기 위해 Flutter의 async 패키지에서 제공하는 CancelableOperation을 활용하게 되었습니다.
CancelableOperation이란?
CancelableOperation은 Future와 비슷하지만, Future와 다르게 중간에 작업을 취소할 수 있는 기능을 제공합니다. 기존의 Future는 await 중에는 취소가 불가능합니다. 반면, CancelableOperation은 아래처럼 cancel() 메서드를 제공하여 작업을 중단시킬 수 있습니다.
코드적용
class HomeCubit extends Cubit<HomeState> {
HomeCubit() : super(const HomeState());
CancelableOperation<void>? _loadOperation;
@override
Future<void> close() {
_loadOperation?.cancel();
return super.close();
}
Future<void> loadPosts() async {
if (_loadOperation != null) {
await _loadOperation?.cancel();
}
try {
emit(state.copyWith(status: HomeStatus.loading));
_loadOperation = CancelableOperation.fromFuture(
Future.delayed(const Duration(seconds: 1)),
);
await _loadOperation?.value;
final mockPosts = _generateMockPosts();
final mockTeamPosts = _generateMockTeamPosts();
emit(state.copyWith(
status: HomeStatus.loaded,
recentPosts: mockPosts,
teamPosts: mockTeamPosts,
ideaPosts: mockPosts.where((post) => post.type == PostType.idea).toList(),
qnaPosts: mockPosts.where((post) => post.type == PostType.qna).toList(),
profilePosts: mockPosts.where((post) => post.type == PostType.profile).toList(),
));
} catch (e) {
if (e is! CancelableOperation<void>) {
emit(state.copyWith(
status: HomeStatus.error,
error: e.toString(),
));
}
} finally {
_loadOperation = null;
}
.
.
.
참고링크
https://pub.dev/documentation/async/latest/async/CancelableOperation-class.html
'Frontend > [Flutter Error]' 카테고리의 다른 글
Comments