【问题标题】:Pausing a stream in dart null safety在 dart null 安全中暂停流
【发布时间】:2021-06-06 22:40:24
【问题描述】:

我正在将 dart 代码转换为 nnbd。

我有以下代码。


   var subscription = response.listen(
        (newBytes) async {
          /// if we don't pause we get overlapping calls from listen
          /// which causes the [writeFrom] to fail as you can't
          /// do overlapping io.
          subscription.pause();

          /// we have new data to save.
          await raf.writeFrom(newBytes);
          subscription.resume();

        });

问题是我收到以下错误:

The non-nullable local variable 'subscription' must be assigned before it can be used.
Try giving it an initializer expression, or ensure that it's assigned on every execution path.

我在这里解决了类似的问题: dart - correct coding pattern for subscription when using null saftey? @lrn 回答了这个问题

但是,模式解决方案模式在这种情况下似乎不起作用。

raf.writeFrom 是一个异步操作,因此我必须使用“异步”方法,这意味着我不能再使用“forEach”解决方案,因为我无权访问订阅对象。

【问题讨论】:

    标签: dart subscription


    【解决方案1】:

    我不认为你写的代码在之前空安全是合法的;您不能在声明变量 (subscription) 之前引用它,并且在评估您使用 (response.listen(...)) 初始化它的表达式之后,声明才完成。您需要将声明与初始化分开以打破循环依赖:

    StreamSubscription<List<int>> subscription;
    subscription = response.listen(...);
    

    【讨论】:

    • 原始代码是合法的,因为listen方法保证在listen返回之前不会生成回调。然而,“延迟”方法对 nnbd 确实有意义。我会测试一下。谢谢!
    • @BrettSutton 在运行时生成或执行listen 回调无关紧要;它不是静态有效的代码,应该在编译时失败。我不知道您的代码以前是如何工作的; DartPad rejects it.
    【解决方案2】:

    如果你真的想使用listen,我会这样做:

    var subscription = response.listen(null);
    subscription.onData((newBytes) async {
      subscription.pause();
      await raf.writeFrom(newBytes);
      subscription.resume();
    });
    

    或者,没有async

    var subscription = response.listen(null);
    subscription.onData((newBytes) {
      subscription.pause(raf.writeFrom(newBytes));
    });
    

    这将暂停订阅,直到 raf.writeFrom 返回的未来完成(但它不应该以错误完成)。

    如果使用listen 不是优先级,我更喜欢使用异步for-in,例如:

    await for (var newBytes in subscription) {
      await raf.writeFrom(newBytes);
    }
    

    它会自动暂停await 处的隐式订阅,并在您返回循环时恢复它。

    对于stream.listenStreamController 构造函数,null 安全性使得在没有回调的情况下先创建它们,然后在回调需要引用订阅/控制器时添加回调变得更好。 (这与链接问题中的答案基本相同,仅适用于onData 而不是onDone。您必须将默认的onData 参数传递给listen,但它可以是null 来支持这一点接近。)

    【讨论】:

      猜你喜欢
      • 2021-10-01
      • 2021-08-12
      • 1970-01-01
      • 2021-06-03
      • 1970-01-01
      • 1970-01-01
      • 2022-06-19
      • 1970-01-01
      • 2021-03-03
      相关资源
      最近更新 更多