2014-02-17 225 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