这里的问题是读取subscription
发生在它仍然可能未分配的地方。实际上并非如此,但我们只知道因为listen
方法承诺在返回之前不调用任何回调。编译器看不到这一点。所以,你需要把阅读移到作业之后。
我会做什么来做到这一点listen
打电话工作:
var buffer = StringBuffer(result);
var subscription = response
.transform(Utf8Decoder())
.transform(LineSplitter())
.listen((line) {
buffer.write(line);
});
subscription.onDone(() {
completer.complete(buffer.toString());
});
我删除了async
来自回调,因为不需要。它使这些函数异步所做的就是返回一个没人会看到的未来。
一般来说,回调Stream
and Future
应该有非异步回调。
我还删除了subscription.cancel
来自onDone
事件处理程序。如果收到“done”事件,则订阅已完成,无需取消。
我还添加了一个字符串缓冲区,以避免重复字符串连接的二次时间和空间复杂度。
查看代码,您似乎在拆分行后立即将行连接起来,也许您需要的只是:
response.transform(Utf8Decoder()).join("").then(completer.complete);
我现在假设拆分+连接是必要的。
在这种情况下,我实际上更愿意做的是使用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);
});
或者,如果在异步函数中:
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);
}