2014-02-17 2 views
2

Я хотел бы иметь простой API на своем http-сервере, поэтому каждый раз, когда я пишу HttpResponse, я использую поток.Как отправить HTTP-ответ, используя поток

так преобразовать все объекты в потоке, т.е. object-> 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) 

Im не знаю, что я делаю неправильно здесь. Я видел примеры, когда входной поток файла был передан в ответ на ответ, но я не могу заставить его работать.

любая помощь оценена!

ответ

1

Есть несколько вещей, чтобы отметить здесь:

Во-первых, JSON и UTF8 кодеры будут производить одно значение, когда вы звоните encode(), так что вы будете создавать Поток только одного значения , Интересно, какое значение вы получите от этого.

Во-вторых, ваш поток фактически не получает никаких значений. onListen вызывается, когда подписывается первый слушатель, но любое значение, возвращаемое с onListen, ни для чего не используется. Для того, чтобы создать поток от одного значения вы, вероятно, хотите использовать new Stream.fromIterable():

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

Так что должно привести значение на самом деле попасть в поток, и заботиться о вашей ошибке. Я думаю, что источником ошибки является то, что входной поток не закрыт, и создание его из Iterable закроет поток, когда Итерируемый будет исчерпан.

pipe() должен также теперь работает, так что вы можете попробовать это:

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

Все сказанное, хотя, я не вижу, как это лучше, чем:

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

скважины конечно, но с простой API, который всегда возвращает Stream, лучше, если вы хотите добавить файлы и другие материалы, которые на самом деле могут создавать данные в кусках. Если я работаю в потоке, я могу преобразовать его (то есть Gzip) в другую часть сервера, не так ли? например, у меня есть случай использования, когда я отправляю большой объект JSON, например, 70 МБ! crazy :) – kamiseq

+0

И вы правы, я почему-то пропустил довольно важную вещь, чтобы использовать controller.add (UTF8.encode (json)); controller.close(); как описано здесь https://www.dartlang.org/articles/creating-streams/ – kamiseq

Смежные вопросы