Skip to content

Commit

Permalink
Merge pull request #21 from alvarobcprado/feature/add-guarded-emits
Browse files Browse the repository at this point in the history
Feature/add guarded emits
  • Loading branch information
alvarobcprado authored May 25, 2023
2 parents 751d831 + 36b7f15 commit 6cafc67
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 23 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 1.0.1
* Added `guardState` method to `ReState` to allow safe emitting of state changes without try-catch blocks

## 1.0.0
* Bumped version to 1.0.0 stable release

Expand Down
48 changes: 27 additions & 21 deletions coverage/lcov.info
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,30 @@ DA:36,0
DA:42,6
DA:43,1
DA:49,12
DA:63,6
DA:70,6
DA:71,0
DA:77,6
DA:78,1
DA:84,6
DA:86,12
DA:87,18
DA:95,12
DA:100,6
DA:101,12
DA:103,6
DA:109,4
DA:112,8
DA:113,8
DA:114,0
DA:115,0
LF:29
LH:25
DA:67,1
DA:73,1
DA:76,1
DA:80,2
DA:83,2
DA:99,6
DA:106,6
DA:107,0
DA:113,6
DA:114,1
DA:120,6
DA:122,12
DA:123,18
DA:131,12
DA:136,6
DA:137,12
DA:139,6
DA:145,4
DA:148,8
DA:149,8
DA:150,0
DA:151,0
LF:34
LH:30
end_of_record
SF:lib\src\re_state_event.dart
DA:13,2
Expand Down Expand Up @@ -121,8 +126,9 @@ DA:98,2
DA:104,4
DA:108,2
DA:111,4
LF:28
LH:26
DA:112,4
LF:29
LH:27
end_of_record
SF:lib\src\re_state_action_event.dart
DA:14,2
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.0.13"
version: "1.0.1"
rxdart:
dependency: transitive
description:
Expand Down
36 changes: 36 additions & 0 deletions lib/src/mixins/re_state_mixin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,42 @@ mixin ReStateMixin<State> on ReSubscriptionHolder {
_stateNotifier.add(state);
}

/// Handles the callback that returns a [State] or a [Future] of [State] in
/// a safe way and emits the returned state.
///
/// If the [callback] returns a [State], then returned value is emitted as the
/// new state. It also pass the last state to the callback as an argument.
///
/// If the [callback] throws an error, then [onError] is called with the last
/// state and the error. The state returned by [onError] is emitted as the new
/// state.
///
/// If [onError] is not provided, then the error is ignored.
///
/// If [initialState] is provided, then the state is set to the [initialState]
/// before calling the callback. Usefull when the callback is an async
/// function and you want to show a loading state.
@protected
Future<void> guardState(
FutureOr<State> Function(State lastState) callback, {
FutureOr<State> Function(Object? error)? onError,
State? initialState,
}) async {
final lastState = state;

if (initialState != null) {
emitState(initialState);
}

try {
emitState(await callback(lastState));
} catch (error) {
if (onError != null) {
emitState(await onError(error));
}
}
}

/// Listens to the state changes.
///
/// [listener] is called whenever a [State] is emitted.
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: re_state_action
description: A simple state management library for Flutter based on States and Actions managed by Streams with RxDart.
repository: https://github.com/alvarobcprado/re_state_action
issue_tracker: https://github.com/alvarobcprado/re_state_action/issues
version: 1.0.0
version: 1.0.1

environment:
sdk: ">=2.12.0 <4.0.0"
Expand Down
20 changes: 20 additions & 0 deletions test/helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ class TestState extends ReState<int> {
void increment() {
emitState(state + 1);
}

void guardIncrement() {
guardState(
(lastState) => lastState + 3,
initialState: 10,
);
}

void guardIncrementError() {
guardState(
(lastState) => throw Exception('error'),
onError: (_) => -1,
);
}

void guardIncrementIgnoreError() {
guardState(
(lastState) => throw Exception('error'),
);
}
}

class TestStateEvent extends ReStateEvent<int, CounterEvent> {
Expand Down
38 changes: 38 additions & 0 deletions test/src/re_state_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,44 @@ void main() {
expect(() => reState.listenState((state) {}), throwsStateError);
},
);

test(
'guardState with initial state resets old state',
() async {
final reState = TestState(0)..increment();
expect(reState.state, 1);
reState.guardIncrement();
await expectLater(reState.stateStream, emitsInOrder([10, 4]));
},
);

test(
'guardState with callback emits state of callback',
() async {
final reState = TestState(0)..guardIncrement();
await Future<void>.delayed(Duration.zero);
await expectLater(reState.state, 3);
},
);

test(
'guardState with callback that throws error emits state of onError',
() async {
final reState = TestState(0)..guardIncrementError();
await Future<void>.delayed(Duration.zero);
expect(reState.state, -1);
},
);

test(
'guardState with callback that throws error and has no onError'
' does not emit state',
() async {
final reState = TestState(0)..guardIncrementIgnoreError();
await Future<void>.delayed(Duration.zero);
await expectLater(reState.state, 0);
},
);
},
);
}

0 comments on commit 6cafc67

Please sign in to comment.