如何使用流发送http响应

时间:2014-02-17 17:14:46

标签: dart data-stream dart-async

我想在我的http服务器中使用简单的API,所以每次写HttpResponse我都会使用流。

所以我将所有对象转换为流,即object-> json-> stream

Stream<List<int>> toStream(Object value) {
    var json = JSON.encode(value);
    var controller = new StreamController<List<int>>(onListen: () => UTF8.encode(json));
    return controller.stream;
}

以后

(response as HttpResponse).addStream(toStream({"a": 1, "B": 2})
.then(() => response.flush())
.catchError((e, stack) {
    _logger.error("Handling ${context.path} finished with an error: $e");
    _logger.debug(stack.toString());
})
.whenComplete(() => response.close());

但我收到错误

Uncaught Error: Bad state: StreamSink is bound to a stream
Stack Trace: 
#0      _StreamSinkImpl.close (io_sink.dart:122)
#1      _HttpOutboundMessage.close (http_impl.dart:481)

我不确定我在这里做错了什么。我看到了File的输入流被传送到响应的示例,但我也无法使其工作。

任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:2)

这里有几点需要注意:

首先,当您调用encode()时,JSON和UTF8编码器将生成单个值,因此您将创建仅包含单个值的Stream。我想知道你从中获得多少价值。

其次,您的Stream实际上并未获得任何值。第一个侦听器订阅时会调用onListen,但onListen返回的任何值都不会用于任何事情。要从单个值创建Stream,您可能希望使用new Stream.fromIterable()

<List<int>> toStream(Object value) =>
    new Stream.fromIterable([UTF8.encode(JSON.encode(value))])

因此,应该使值实际进入Stream,并处理您的错误。我认为你的错误来源是输入流没有关闭,从Iterable创建它会在Iterable耗尽时关闭Stream。

pipe()现在也可以使用,所以你可以试试这个:

toStream({"a": 1, "B": 2}).pipe(response)
  .then((_) {
    print("done");
  });

尽管如此,我不知道这比这更好:

response
  ..write(JSON.encode(value))
  ..close();