Skip to content
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

Don't trigger unneeded ActionSpyEvent for AsyncAction #784

Merged
merged 11 commits into from
Jun 11, 2022
4 changes: 4 additions & 0 deletions mobx/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 2.0.7+3

- Fixed unnecessary ActionSpyEvents being triggered for AsyncAction

## 2.0.7+1 - 2.0.7+2

- Package upgrades
Expand Down
2 changes: 1 addition & 1 deletion mobx/lib/mobx.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,4 @@ export 'package:mobx/src/core.dart'
export 'package:mobx/src/core/atom_extensions.dart';

/// The current version as per `pubspec.yaml`
const version = '2.0.7+2';
const version = '2.0.7+3';
21 changes: 6 additions & 15 deletions mobx/lib/src/api/async/async_action.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class AsyncAction {
}

Future<R> run<R>(Future<R> Function() body) async {
final actionInfo = _actions.startAction(name: _actions.name);
try {
return await _zone.run(body);
} finally {
Expand All @@ -32,33 +33,23 @@ class AsyncAction {
// Needed to make sure that all mobx state changes are
// applied after `await run()` completes, not sure why.
await Future.microtask(_noOp);
_actions.endAction(actionInfo);
}
}

static dynamic _noOp() => null;

R _run<R>(Zone self, ZoneDelegate parent, Zone zone, R Function() f) {
final actionInfo = _actions.startAction(name: '${_actions.name}(Zone.run)');
try {
final result = parent.run(zone, f);
return result;
} finally {
_actions.endAction(actionInfo);
}
final result = parent.run(zone, f);
return result;
}

// Will be invoked for a catch clause that has a single argument: exception or
// when a result is produced
R _runUnary<R, A>(
Zone self, ZoneDelegate parent, Zone zone, R Function(A a) f, A a) {
final actionInfo =
_actions.startAction(name: '${_actions.name}(Zone.runUnary)');
try {
final result = parent.runUnary(zone, f, a);
return result;
} finally {
_actions.endAction(actionInfo);
}
final result = parent.runUnary(zone, f, a);
return result;
}

// Will be invoked for a catch clause that has two arguments: exception and stacktrace
Expand Down
2 changes: 1 addition & 1 deletion mobx/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: mobx
version: 2.0.7+2
version: 2.0.7+3
description: "MobX is a library for reactively managing the state of your applications. Use the power of observables, actions, and reactions to supercharge your Dart and Flutter apps."

homepage: https://github.com/mobxjs/mobx.dart
Expand Down
37 changes: 37 additions & 0 deletions mobx/test/spy_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:mobx/mobx.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -124,6 +126,41 @@ void main() {
d();
});

test('spy-event is raised only once when an AsyncAction is executed',
() async {
var eventCount = 0;
var endEventCount = 0;
final d = mainContext.spy((event) {
if (event is ActionSpyEvent) {
eventCount += 1;
}

if (event is EndedSpyEvent && event.type == 'action') {
endEventCount += 1;
}
});

final actionCompleter = Completer();
final microtaskCompleter = Completer();
AsyncAction('test').run(() async {
scheduleMicrotask(() {
microtaskCompleter.complete();
});
actionCompleter.complete();
});
await actionCompleter.future;
await microtaskCompleter.future;

// This is needed to ensure that all spy callbacks are executed
// before moving on to `expect`s.
await Future.value();

expect(eventCount, 1);
expect(endEventCount, 1);

d();
});

test('spy-event is raised when a Reaction is executed', () {
final o = Observable(0);
final d1 = reaction((_) => o.value, (_) {}, name: 'test');
Expand Down