Async await

135 views
Skip to first unread message

Greg Lowe

unread,
Nov 15, 2014, 12:58:32 AM11/15/14
to mi...@dartlang.org
Hi all,

I'm still trying to get my head around the async await syntax.

One thing that caught me by surprise, though perhaps I misunderstand, is that await expression by default does not "block" for streams.

I had assumed that the await expression when evaluated on a stream would return a list.

Here's an example of what I mean:

Stream<int> getResults() async* {
 
yield 42;
 
yield 43;
 
yield 44;
}

main
() async {
 
var results = await getResults();    // This has no effect, need to write await getResults().toList();
 
print(results);
}



Another thing that took me a while to figure out is how to thread a timeout value through various calls to await. As in this example here:


I would be curious if anyone has advice on a cleaner way to do this. 

The naive solution is to wrap a single timeout around the whole function - but I believe this could result in the async while loop continuing to run even after the timeout has expired - but I'm not sure about this. Sorry if the explanation isn't very clear - I'm still trying to understand this handy new feature ;)

Cheers,
Greg.

Lasse R.H. Nielsen

unread,
Nov 15, 2014, 5:59:28 AM11/15/14
to mi...@dartlang.org
On Sat, Nov 15, 2014 at 6:58 AM, Greg Lowe <greg...@gmail.com> wrote:
Hi all,

I'm still trying to get my head around the async await syntax.

One thing that caught me by surprise, though perhaps I misunderstand, is that await expression by default does not "block" for streams.

I had assumed that the await expression when evaluated on a stream would return a list.

Here's an example of what I mean:

Stream<int> getResults() async* {
 
yield 42;
 
yield 43;
 
yield 44;
}

main
() async {
 
var results = await getResults();    // This has no effect, need to write await getResults().toList();
 
print(results);
}


There is no automatic conversion from a Stream to a synchronous value, and there really can't be the way Streams are defined.
A Stream can have multiple error events. Converting into a single result would mean fixing on a single way to handle that.
What you can, eventually, do instead is either:
   yield* getResults();  // in an async* function, yields every element of the stream.
or 
   await for(var v in getResults()) {
     ... do something with v
   }
Those are the ways to consume a Stream in async/await syntax - by acting on each event individualy.

 
Another thing that took me a while to figure out is how to thread a timeout value through various calls to await. As in this example here:


I would be curious if anyone has advice on a cleaner way to do this. 

The naive solution is to wrap a single timeout around the whole function - but I believe this could result in the async while loop continuing to run even after the timeout has expired - but I'm not sure about this. Sorry if the explanation isn't very clear - I'm still trying to understand this handy new feature ;)

It sounds like it's correct. When you trigger a timeout because some operation hasn't completed in time, that operation is still running (well, it could have crashed silently, but there is still no way to know that). That is why it's generally a good idea to not do timeouts on operations with side effects. A timeout is better suited for an operation that completes with the value that you want, but doesn't change any state. If the timeout triggers, the value will just be dropped, but if there were side effects, you have no control over those.

/L

Greg Lowe

unread,
Nov 15, 2014, 5:30:38 PM11/15/14
to mi...@dartlang.org
A Stream can have multiple error events. Converting into a single result would mean fixing on a single way to handle that.

I assumed that "await stream" would behave exactly like "await stream.toList()" does. I believe stream.toList() returns the first error on the stream, and cancels the subscription after the first error.

The fact that "await stream" is a no-op, and a silent one without warnings or hints is non-intuitive (for me at least).

Ideally it would be possible to teach the analyzer to provide a hint when awaiting on a non-future. However I understand this is difficult as sometimes you actually want this behaviour.

Warren

unread,
Nov 15, 2014, 6:37:31 PM11/15/14
to mi...@dartlang.org


Is async* and yield actually supported in the current dev release? (1.8.0.dev_04_00 (DEV))

I am  trying this out. The editor does not complain, but when I run I get "function block expected" on the async*  block.


await and async are working OK - so I do have experimental support turned on 

Greg Lowe

unread,
Nov 15, 2014, 6:55:35 PM11/15/14
to mi...@dartlang.org
I haven't tried using async*/yield yet. The code example was just my guess at how it is supposed to look.

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

Reply all
Reply to author
Forward
Message has been deleted
0 new messages