readSnapshot function

Future<DbSnapshot?> readSnapshot(
  1. String path, {
  2. DbQuery? query,
  3. Duration settle = const Duration(milliseconds: 400),
  4. Duration timeout = const Duration(seconds: 15),
})

readValue, with the snapshot's child order kept.

The façade's get() needs it: DataSnapshot.children is ordered, and the value on its own is not.

Implementation

Future<DbSnapshot?> readSnapshot(
  String path, {
  DbQuery? query,
  Duration settle = const Duration(milliseconds: 400),
  Duration timeout = const Duration(seconds: 15),
}) async {
  final completer = Completer<DbSnapshot?>();
  DbSnapshot? last;
  var seen = false;
  Timer? quiet;

  final source = query == null ? onValue(path) : onQueryValue(path, query);
  final sub = source.listen(
    (s) {
      last = s;
      seen = true;
      quiet?.cancel();
      quiet = Timer(settle, () {
        if (!completer.isCompleted) completer.complete(last);
      });
    },
    onError: (Object e) {
      if (!completer.isCompleted) completer.completeError(e);
    },
  );

  try {
    return await completer.future.timeout(
      timeout,
      onTimeout: () => seen ? last : null,
    );
  } finally {
    quiet?.cancel();
    await sub.cancel();
  }
}