Skip to content

Commit ecd1a8d

Browse files
Merge branch 'FME-11223-web-support-fix-onUpdated-with-async-callbacks' into FME-11223-web-support-js-interop-improvements
2 parents 54b9442 + f1c2518 commit ecd1a8d

File tree

2 files changed

+28
-24
lines changed

2 files changed

+28
-24
lines changed

splitio_web/lib/splitio_web.dart

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,9 @@ class SplitioWeb extends SplitioPlatform {
741741
_factory.UserConsent.setStatus(enabled.toJS);
742742
}
743743

744+
// To ensure the public `onXXX` callbacks and `whenXXX` methods work correctly,
745+
// the `onXXX` method implementations always return a Future or Stream that waits for the client to be initialized.
746+
744747
@override
745748
Future<void>? onReady(
746749
{required String matchingKey, required String? bucketingKey}) async {
@@ -813,31 +816,37 @@ class SplitioWeb extends SplitioPlatform {
813816
@override
814817
Stream<void>? onUpdated(
815818
{required String matchingKey, required String? bucketingKey}) {
816-
final client = _clients[buildKeyString(matchingKey, bucketingKey)];
817-
818-
if (client == null) {
819-
return null;
820-
}
819+
// To ensure the public `onUpdated` callback and `whenUpdated` method work correctly,
820+
// this method always return a stream, and the StreamController callbacks
821+
// are async to wait for the client to be initialized.
821822

822823
late final StreamController<void> controller;
823824
final JSFunction jsCallback = (() {
824825
if (!controller.isClosed) {
825826
controller.add(null);
826827
}
827828
}).toJS;
829+
final registerJsCallback = () async {
830+
final client = await _getClient(
831+
matchingKey: matchingKey,
832+
bucketingKey: bucketingKey,
833+
);
834+
client.on(client.Event.SDK_UPDATE, jsCallback);
835+
};
836+
final deregisterJsCallback = () async {
837+
final client = await _getClient(
838+
matchingKey: matchingKey,
839+
bucketingKey: bucketingKey,
840+
);
841+
client.off(client.Event.SDK_UPDATE, jsCallback);
842+
};
828843

829844
controller = StreamController<void>(
830-
onListen: () {
831-
client.on(client.Event.SDK_UPDATE, jsCallback);
832-
},
833-
onPause: () {
834-
client.off(client.Event.SDK_UPDATE, jsCallback);
835-
},
836-
onResume: () {
837-
client.on(client.Event.SDK_UPDATE, jsCallback);
838-
},
845+
onListen: registerJsCallback,
846+
onPause: deregisterJsCallback,
847+
onResume: registerJsCallback,
839848
onCancel: () async {
840-
client.off(client.Event.SDK_UPDATE, jsCallback);
849+
await deregisterJsCallback();
841850
if (!controller.isClosed) {
842851
await controller.close();
843852
}

splitio_web/test/splitio_web_test.dart

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,34 +1038,29 @@ void main() {
10381038
});
10391039

10401040
test('onUpdated', () async {
1041-
// Precondition: client is initialized before onUpdated is called
1042-
await _platform.getClient(
1043-
matchingKey: 'matching-key', bucketingKey: 'bucketing-key');
10441041
final mockClient =
10451042
mock.mockFactory.client(buildJsKey('matching-key', 'bucketing-key'));
10461043

10471044
final stream = _platform.onUpdated(
10481045
matchingKey: 'matching-key', bucketingKey: 'bucketing-key')!;
10491046
final subscription = stream.listen(expectAsync1((_) {}, count: 3));
1047+
await Future<void>.delayed(Duration.zero); // onListen is async
10501048

10511049
// Emit SDK_UPDATE events. Should be received
10521050
mockClient.emit(mockClient.Event.SDK_UPDATE);
1053-
10541051
mockClient.emit(mockClient.Event.SDK_UPDATE);
10551052

1056-
await Future<void>.delayed(
1057-
const Duration(milliseconds: 100)); // let events deliver
1058-
10591053
// Pause subscription and emit SDK_UPDATE event. Should not be received
10601054
subscription.pause();
1055+
await Future<void>.delayed(Duration.zero); // onPause is async
10611056
mockClient.emit(mockClient.Event.SDK_UPDATE);
1062-
await Future<void>.delayed(const Duration(milliseconds: 100));
10631057

10641058
// Resume subscription and emit SDK_UPDATE event. Should be received
10651059
subscription.resume();
1060+
await Future<void>.delayed(Duration.zero); // onResume is async
10661061
mockClient.emit(mockClient.Event.SDK_UPDATE);
1067-
await Future<void>.delayed(const Duration(milliseconds: 100));
10681062

1063+
await Future<void>.delayed(Duration.zero); // let last event deliver before cancel
10691064
await subscription.cancel();
10701065
});
10711066
});

0 commit comments

Comments
 (0)