It just occurred to me that it would make sense to stream strings, each representing an element from a database query instead of returning the whole list of them at the end of the process, this might get the first result earlier on the browser. So I tried to implement this with Redstone
which uses Shelf
. Here is my basic test
@app.Route ('/testStream')
testSream ()
{
StreamController<String> controller = new StreamController<String> ();
() async
{
var initialTime = new DateTime.now();
await new Future.delayed (new Duration (seconds: 1));
controller.add("hello\n");
await new Future.delayed (new Duration (seconds: 10));
controller.add("chao\n");
var finalTime = new DateTime.now().difference(initialTime);
controller.add(finalTime.toString());
controller.close();
}();
Stream<List<int>> intStream = controller.stream.map((s) => s.codeUnits);
return new shelf.Response.ok (intStream);
}
Just for some context, the Linked-in guys use "text streaming" in a pattern they got from Facebook to render parts of the page quickly and insert some latter (as its available), they implement this in Playframework (Scala) where they use Enumerables
which seem behave just like Dart streams. You can see it in this video.
The problem with my code is that while I expected it to show "hello"
after 1 second, and "chao"
10 seconds later. What I get is 11 seconds of waiting and then the complete text. As you see, I am responding a Shelf.Response
with a Stream<List<int>>
where each List<int>
is just a the string from the original stream converted into bytes.
Is this a Shelf problem/feature, or is Redstone messing around with the response and converting it to a future? Is there any work around?
EDIT
What I want to get
Nothing for 1 second.
After 1 second
hello
After 11 seconds
hello
chao
0:00:11.009000
What I really get
Nothing for 1 second.
After 11 seconds
hello
chao
0:00:11.009000