dart-使用空安全协议时订阅的正确编码模式? [英] dart - correct coding pattern for subscription when using null saftey?

查看:127
本文介绍了dart-使用空安全协议时订阅的正确编码模式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已启用dart 2.8实验型空安全提示.

I've enabled the dart 2.8 experimental null saftey.

我有以下退出代码.

StreamSubscription<String> subscription;
    subscription =
        response.transform(Utf8Decoder()).transform(LineSplitter()).listen(
      (line) async {
        result += line;
      },
      onDone: () async {
        unawaited(subscription.cancel());
        completer.complete(result);
      },
    );

启用null安全功能后,我在"onDone"方法中收到了一个错误,该方法调用了subscription.cancl

With null saftey enabled I get a error in the 'onDone' method where it calls subscription.cancl

"The expression is nullable and must be null-checked before it can be used.
Try checking that the value isn't null before using it.",

我可以通过在取消调用之前放置条件来解决此问题,但这似乎是不必要的,因为实际上订阅永远不能为空.

I can fix the problem by putting a conditional before the call to cancel, but this seems unnecessary as in reality subscription can never be null.

有没有一种编码模式可以将订阅声明为非空?

Is there a coding pattern that allows subscription to be declared as non-null?

推荐答案

这里的问题是 subscription 的读取发生在仍未分配的位置.实际上,它不是,但是我们只知道这是因为 listen 方法保证不会在返回之前调用任何回调.编译器看不到.因此,您需要在分配后将读数移动到.

The problem here is that the read of subscription happens at a place where it's still potentially unassigned. It isn't, actually, but we only know that because the listen method promises not to call any of the callbacks before returning. The compiler can't see that. So, you need to move the reading to after the assignment.

要使此 listen 通话有效,我会怎么做:

What I'd do to make this listen call work:

var buffer = StringBuffer(result);
var subscription = response
  .transform(Utf8Decoder())
  .transform(LineSplitter())
  .listen((line) {
    buffer.write(line);
  });
subscription.onDone(() {
    completer.complete(buffer.toString());
  });

我从回调中删除了 async ,因为它不是必需的.使这些功能异步的所有作用就是返回一个没人能看得到的未来.通常, Stream Future 上的回调应具有非异步回调.

I removed the async from the callbacks because it is not needed. All it does to make these functions async is to return a future that no-one would ever look at. In general, the callbacks on Stream and Future should have non-async callbacks.

我还从 onDone 事件处理程序中删除了 subscription.cancel .如果您收到完成"的通知,事件,则表示订阅已完成,无需取消订阅.

I also removed the subscription.cancel from the onDone event handler. If you get a "done" event, the subscription is done, there is no need to cancel it.

我还添加了一个字符串缓冲区,以避免重复的字符串串联的二次时间和空间复杂性.

I also added a string buffer to avoid the quadratic time and space complexity of repeated string concatenation.

看看代码,您似乎在分割行之后将它们串联起来,也许您所需要的只是:

Looking at the code, you seem to be concatenating lines right after splitting them, maybe all you need is:

  response.transform(Utf8Decoder()).join("").then(completer.complete);

我现在假设拆分+联接是必需的.

I'll assume for now that the splitting+joining is necessary.

在那种情况下,我实际上更愿意做的是使用 listen :

In that case, what I'd actually prefer to do instead is of using listen is:

var buffer = StringBuffer();
response
  .transform(Utf8Decoder())
  .transform(LineSplitter())
  .forEach((line) {
    buffer.write(line);
  }).then(() {
    completer.complete(buffer.toString());
  }, onError: (e, s) {
    completer.completeError(e, s);
  });

或者,如果在异步函数中:

or, if in an async function:

try {
  var buffer = StringBuffer();
  await for (var line in response.transform(Utf8Decoder()).transform(LineSplitter())) {
    buffer.write(line);
  }
  completer.complete(buffer.toString());  
} catch(e, s) {
  completer.completeError(e, s);
}

这篇关于dart-使用空安全协议时订阅的正确编码模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆