2

我想在我的 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 的输入流通过管道传输到响应的示例,但我也无法使其工作。

任何帮助表示赞赏!

4

1 回答 1

2

这里有几点需要注意:

首先,当您调用 时,JSON 和 UTF8 编码器将产生一个值encode(),因此您将创建一个只有一个值的 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();
于 2014-02-17T20:03:01.883 回答