rxdart行为主题散发出以前的事件,不仅是最后一个值

发布于 2025-02-06 03:44:31 字数 1467 浏览 2 评论 0原文

我对rxdart 。 通常,行为主体只能散发出流的最后值:

一种特殊的streamController捕获已添加到控制器的最新项目,并将其作为任何新侦听器的第一项。

但是在我的情况下,它也在流中排出所有以前的值,我不知道为什么。

我有以下测试集合:

class TestBloc {

  final _controller = BehaviorSubject.seeded([]);

  Stream get stream$ => _controller.stream;

  TestBloc(BehaviorSubject subject) {
    subject.listen((e) {
      print("listen $e");
      _controller.add([e]);
    });
  }

}

带测试案例:

    test("test bloc", () async {
      final subject = BehaviorSubject();

      final bloc = TestBloc(subject);

      subject.add(1);
      subject.add(2);

      // Uncomment next line to make test pass
      // await expectLater(subject.stream, emits(2)); 

      // Test will fail here
      await expectLater(bloc.stream$, emits([2]));
    });

测试失败,因为从主题发出的所有事件发出,而不仅是预期的最后:

Expected: should emit an event that [2]
  Actual: <Instance of 'BehaviorSubject<List<dynamic>>'>
   Which: emitted * []
                  * [1]
                  * [2]
            which emitted an event that at location [0] is [] which shorter than expected

这是rxdart的问题,还是我做错了什么。 要我理解.add()在侦听器中呼叫的效果应与在测试用例中添加连续添加的效果相同,但似乎并非如此。

I have a strange issue with rxdart BehaviorSubject.
Normally BehaviorSubject should only emit the last value to the stream:

A special StreamController that captures the latest item that has been added to the controller, and emits that as the first item to any new listener.

But in my case it is emitting all the previous values on the stream too and I dont know why.

I have the following test bloc:

class TestBloc {

  final _controller = BehaviorSubject.seeded([]);

  Stream get stream$ => _controller.stream;

  TestBloc(BehaviorSubject subject) {
    subject.listen((e) {
      print("listen $e");
      _controller.add([e]);
    });
  }

}

With test case:

    test("test bloc", () async {
      final subject = BehaviorSubject();

      final bloc = TestBloc(subject);

      subject.add(1);
      subject.add(2);

      // Uncomment next line to make test pass
      // await expectLater(subject.stream, emits(2)); 

      // Test will fail here
      await expectLater(bloc.stream$, emits([2]));
    });

The test fails because all the events from the subject where emitted and not only the expected last:

Expected: should emit an event that [2]
  Actual: <Instance of 'BehaviorSubject<List<dynamic>>'>
   Which: emitted * []
                  * [1]
                  * [2]
            which emitted an event that at location [0] is [] which shorter than expected

Is this an issue with rxdart or am I doing something wrong.
To my understanding the .add() call in the listener should have the same effect as calling add consecutive like in the test case but it seems not to.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

柏林苍穹下 2025-02-13 03:44:31

代码精神

当与流并发时,相同的行为可能会面临。
为了说明这一点,您可以在代码中添加夫妇调试行:

class TestBloc {

  final _controller = BehaviorSubject.seeded([]);

  Stream get stream$ => _controller.stream;

  TestBloc(BehaviorSubject subject) {
    subject.listen((e) {
      print("listen $e");
      print('A: ${DateTime.now()}');
      _controller.add([e]);
      print('B: ${DateTime.now()}');
    });
  }

}

测试案例:

test("test bloc", () async {
      final subject = BehaviorSubject();

      final bloc = TestBloc(subject);

      subject.add(1);
      subject.add(2);

      // Uncomment next line to make test pass
      // await expectLater(subject.stream, emits(2));

      /// If you uncomment next comment it will fix the problem
      /// this await Future.delayed(Duration.zero) is added
      /// to avoid executing the expectLater() before
      /// the listener in TestBloc constructor.

      // await Future.delayed(Duration.zero);
      print('C: ${DateTime.now()}');
      await expectLater(bloc.stream$, emits([2]));
      print('D: ${DateTime.now()}');
  });

如果运行此代码,则会看到:

C: 2022-08-24 23:52:23.910217
listen 1
A: 2022-08-24 23:52:23.941463
B: 2022-08-24 23:52:23.942454
listen 2
A: 2022-08-24 23:52:23.945855
B: 2022-08-24 23:52:23.946078

因此

await expectLater(bloc.stream$, emits([2]));

已执行以前执行

_controller.add([e]);

,但是当您的删节时

await expectLater(subject.stream, emits(2));

,它的角色与

await Future.delayed(Duration.zero);

Code Spirit

The same behaviour could be faced when messing up with stream concurrency.
To illustrate this you can add couple debug lines to your code:

class TestBloc {

  final _controller = BehaviorSubject.seeded([]);

  Stream get stream$ => _controller.stream;

  TestBloc(BehaviorSubject subject) {
    subject.listen((e) {
      print("listen $e");
      print('A: ${DateTime.now()}');
      _controller.add([e]);
      print('B: ${DateTime.now()}');
    });
  }

}

test case:

test("test bloc", () async {
      final subject = BehaviorSubject();

      final bloc = TestBloc(subject);

      subject.add(1);
      subject.add(2);

      // Uncomment next line to make test pass
      // await expectLater(subject.stream, emits(2));

      /// If you uncomment next comment it will fix the problem
      /// this await Future.delayed(Duration.zero) is added
      /// to avoid executing the expectLater() before
      /// the listener in TestBloc constructor.

      // await Future.delayed(Duration.zero);
      print('C: ${DateTime.now()}');
      await expectLater(bloc.stream$, emits([2]));
      print('D: ${DateTime.now()}');
  });

If you run this code you will see:

C: 2022-08-24 23:52:23.910217
listen 1
A: 2022-08-24 23:52:23.941463
B: 2022-08-24 23:52:23.942454
listen 2
A: 2022-08-24 23:52:23.945855
B: 2022-08-24 23:52:23.946078

thus

await expectLater(bloc.stream$, emits([2]));

is executed before

_controller.add([e]);

but when you uncomment

await expectLater(subject.stream, emits(2));

it plays the same role as

await Future.delayed(Duration.zero);
夏の忆 2025-02-13 03:44:31

因此,如果您期望最后一项Willbe [2],则必须将[2]作为预期值推动。如果您需要收听多个值,也可以推动多个值

测试(“ test Bloc”,()async {
最终主题=行为主题();

  final bloc = TestBloc(subject);

  subject.add(2);

  // Test will successful
  await expectLater(bloc.stream$, emits([2]));
});

so if you expect the last item willbe [2], then you have to push [2] as the expected value.if you need to listen for multiple values you can also push multiple values

test("test bloc", () async {
final subject = BehaviorSubject();

  final bloc = TestBloc(subject);

  subject.add(2);

  // Test will successful
  await expectLater(bloc.stream$, emits([2]));
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文