如何根据您在 Dart 中无法控制的 Stream 返回 Future?

Posted

技术标签:

【中文标题】如何根据您在 Dart 中无法控制的 Stream 返回 Future?【英文标题】:How do you return a Future based off a Stream you don't control in Dart? 【发布时间】:2014-04-09 04:42:18 【问题描述】:

我有一种情况,我期望来自 Stream 的单个值,但因为它是由浏览器提供的,所以我不能依赖简单地调用 streamSub.single。目前,我正在创建一个显式的StreamController,这样我就可以轻松地从中生成一个Future,同时保证它只会得到一个响应。然而,这最终比我预期的要设置的开销要多得多,这让我觉得我错过了一些东西。当前代码如下:

StreamController<String> streamCtrlr = new StreamController<String>();
var popup = window.open(targetUrl, "Auth Window"); 
//The popup above will call window.opener.postMessage, so listen for messages
StreamSubscription sub = window.onMessage.listen(null);
sub.onData((Event)
  /* Logic goes here */
  sub.cancel();
  popup.close();
  streamCtrlr.add(Event.data);
  streamCtrlr.close();
);  
return streamCtrlr.stream.single;

如何重写此代码,从而不需要中介 StreamController

【问题讨论】:

【参考方案1】:

为什么你不能依靠打电话streamSub.single?是因为可能有不止一条消息吗?

您的示例代码在所有情况下都选择第一个事件,因此要获得相同的行为,您可以使用window.onMessage.first 而不是window.onMessage.single。 如果没有第一个事件,它仍然会导致错误(但我认为 DOM 事件处理程序不会发生这种情况 - 它们从不发送完成事件),否则它将给出一个由第一个事件完成的未来。

您还想提取事件数据,因此您可能需要:

return window.onMessage.first.then((event) 
  /* Logic goes here */
  popup.close();
  return event.data;
);

【讨论】:

是的,我对使用 sub.single 持谨慎态度,因为管道中可能会有多条消息。我实际上首先尝试过,但它没有触发第一个 postMessage 调用的 onData ,第二个引发了错误。我会先尝试流。当使用 stream.first 时,它是返回带有 自订阅 以来的第一个事件的未来,还是返回自创建流以来的第一个事件(在这种情况下意味着自 DOM 加载以来)?跨度> 按照@lrn 的建议,我选择使用firstWhere 并使用布尔闭包来检查消息的来源,以确保它来自我期望的域。完美运行! =D 我相信 DOM 流充当广播流,因此它们不应缓冲您收听之前的事件。

以上是关于如何根据您在 Dart 中无法控制的 Stream 返回 Future?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Dart 中测试异步 Stream

如何从 JavaScript 监听器创建 Dart Stream

如何通过 Dart/Flutter 中的“application/octet-stream”将 png 文件发送到 Microsoft Custom Vision?

Dart异步编程之Stream

Dart - 相当于 Dart 的 C# Stream/MemoryStream 和 stream.WriteByte(..)

dart Iterable、Stream