2014-02-17 166 views
2

我想在我的http服务器中有简单的API,所以每次我写入HttpResponse时都使用流。如何使用流发送http响应

,所以我将所有对象转换成数据流,即对象 - > json->流

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

有几件事情要注意这里:

首先,JSON和UTF8编码器会产生当你调用encode()一个值,所以你将创建只是一个单一的价值流。我想知道你从中得到了多少价值。

其次,您的流实际上没有获得任何值。当第一个侦听器订阅时调用onListen,但从onListen返回的任何值都不用于任何内容。为了从您可能需要使用new Stream.fromIterable()单个值创建流:

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

所以这应该引起价值真正得到进入流,并把你的错误的照顾。我认为你错误的根源在于输入流没有关闭,并且在Iterable耗尽时从Iterable创建它将关闭流。

pipe()也应该现在的工作,所以你可以试试这个:

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

所有虽然说,我不明白这是怎么好过:当然

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

很好,但有总是返回流的简单API更好,如果你想添加文件和其他东西,实际上可以产生大块数据。如果我在流上工作,我可以在服务器的其他部分转换它(即Gzip),我错了吗? 例如我有一个用例,我发送像70MB这样的大型JSON对象!疯狂:) – kamiseq

+0

你是对的,我不知何故错过了使用controller.add(UTF8.encode(json))的非常重要的事情; controller.close();如此处所述https://www.dartlang.org/articles/creating-streams/ – kamiseq