How do you usually handle timeouts in your code?

1,666 views
Skip to first unread message

Kai Sellgren

unread,
Apr 22, 2013, 11:25:39 AM4/22/13
to mi...@dartlang.org
There are plenty of cases where things may be running for a long time like HTTP requests, for example.

Does anyone take care of timeouts? Do you just use the Timer class? I think it would be nice to have a simple way to specify a timeout for most async stuff, so that nothing hangs for a long period of time.

For example, right now my app is stuck for the past 2 mins for downloading an image over the Internet... maybe we should have a timeout feature in the HTTP package. If I now kill the app and start over it will then download it instantly.

Sean Eagan

unread,
Apr 22, 2013, 3:32:41 PM4/22/13
to General Dart Discussion

You should able to do:

(Warning: untested code)

class TimeoutException {/*...*/}

Future withTimeout(Future future, Duration duration) {
  var completer = new Completer();
  var timer = new Timer(duration, () => completer.completeException(new TimeoutException()));
  future.then((v) {timer.cancel(); completer.complete(v);}, onError: (e) {timer.cancel(); completer.completeException(e););
  return completer.future;
}

But this could still lead to getting the TimeoutException, and a completed Future, since one can't currently detect whether the Timer.cancel calls are successful, so I filed:


And timeout functionality seems common enough to be in dart:async itself, so I filed:


(hope I didn't duplicate existing bugs)

Cheers,
Sean Eagan


--
Consider asking HOWTO questions at Stack Overflow: http://stackoverflow.com/tags/dart
 
 

Bob Nystrom

unread,
Apr 22, 2013, 4:43:45 PM4/22/13
to General Dart Discussion

On Mon, Apr 22, 2013 at 8:25 AM, Kai Sellgren <kaise...@gmail.com> wrote:
Does anyone take care of timeouts? Do you just use the Timer class? I think it would be nice to have a simple way to specify a timeout for most async stuff, so that nothing hangs for a long period of time.

Pub cares about timeouts. We use Timer, but we've wrapped it in this helper function:

/// Wraps [input] to provide a timeout. If [input] completes before
/// [milliseconds] have passed, then the return value completes in the same way.
/// However, if [milliseconds] pass before [input] has completed, it completes
/// with a [TimeoutException] with [description] (which should be a fragment
/// describing the action that timed out).
///
/// Note that timing out will not cancel the asynchronous operation behind
/// [input].
Future timeout(Future input, int milliseconds, String description) {
  var completer = new Completer();
  var timer = new Timer(new Duration(milliseconds: milliseconds), () {
    completer.completeError(new TimeoutException(
        'Timed out while $description.'));
  });
  input.then((value) {
    if (completer.isCompleted) return;
    timer.cancel();
    completer.complete(value);
  }).catchError((e) {
    if (completer.isCompleted) return;
    timer.cancel();
    completer.completeError(e);
  });
  return completer.future;
}

I'd be happy if something along these lines was in dart:async.

- bob

Jos Hirth

unread,
Apr 22, 2013, 5:04:18 PM4/22/13
to mi...@dartlang.org
On Monday, April 22, 2013 10:43:45 PM UTC+2, Bob Nystrom wrote:

I'd be happy if something along these lines was in dart:async.

Sounds like a good idea.

This would fix:

http://dartbug.com/3255 - abandoned Completers should fire NotCompletedException() / TimeoutException()

http://dartbug.com/7366 - Missing timeout handling in WebSocketConnection in dart:io

http://dartbug.com/7367 - Missing timeout handling in WebSocket in dart:html

http://dartbug.com/10119 - Add timeout functionality to dart:async

Kai Sellgren

unread,
Apr 22, 2013, 6:47:20 PM4/22/13
to mi...@dartlang.org


On Tuesday, April 23, 2013 12:04:18 AM UTC+3, Jos Hirth wrote:
On Monday, April 22, 2013 10:43:45 PM UTC+2, Bob Nystrom wrote:

I'd be happy if something along these lines was in dart:async.

Sounds like a good idea.


Exactly what I'd like to see too.

You should able to do:
... 

The nice thing with async in Dart is that everything works the same way, no matter what library is in use. That said, I'd prefer not to wrap calls or pass extra params to lib methods in random and different ways depending on the design choices the library author made. For now, I guess that's the only way to go.

pev...@sonardesign.com

unread,
Apr 24, 2013, 4:44:29 PM4/24/13
to mi...@dartlang.org
Something like this wrapped timer would help.  
I would like some way of setting a timeout of an async operation at time of creation rather than have yet another timer object being allocated.
If possible on the dartvm at least on Win32, it would be nice if we had a way of passing a timeout when setting up a async task to WaitForSingleObject via dart.  A quick search of the source shows WaitForSingleObject is often paired up with INFINITE.  Propagating the timeout down that far would leverage what the underlying OS is trying to do for us.  It could also simplify the call stack, which already seems to get deep when using Futures.
Perhaps when compiling to javascript it could fallback to an encapsulated timer, but I don't see why the VM need be tied to that.

(I'm a dart newbie)

Allan MacDonald

unread,
Apr 24, 2013, 5:43:57 PM4/24/13
to mi...@dartlang.org
Would Future.delayed(Duration duration, [T computation()]) be helpful here?


--

jm

unread,
Apr 25, 2013, 1:44:35 PM4/25/13
to Dart Discussion


On 22 abr, 16:43, Bob Nystrom <rnyst...@google.com> wrote:
> Future timeout(Future input, int milliseconds, String description) {
>   var completer = new Completer();
>   var timer = new Timer(new Duration(milliseconds: milliseconds), () {
>     completer.completeError(new TimeoutException(
>         'Timed out while $description.'));
>   });
>   input.then((value) {
>     if (completer.isCompleted) return;
>     timer.cancel();
>     completer.complete(value);
>   }).catchError((e) {
>     if (completer.isCompleted) return;
>     timer.cancel();
>     completer.completeError(e);
>   });
>   return completer.future;
>
> }
>
> I'd be happy if something along these lines was in dart:async.
>

A couple of newbie questions:

Why not have this be a method of a future? Because it creates a
dependency on the timer?

Today I saw this code from Task.js:

spawn(function*() {
var data = yield $.ajax(url);
$('#result').html(data);
var status = $('#status').html('Download complete.');
yield status.fadeIn().promise();
yield sleep(2000);
status.fadeOut();
});

How is this done in Dart?

I like the select statement from Go. I kind of expected it in Dart,
why isn't it?



Bob Nystrom

unread,
Apr 25, 2013, 4:11:13 PM4/25/13
to General Dart Discussion
On Thu, Apr 25, 2013 at 10:44 AM, jm <janm...@gmail.com> wrote:
Why not have this be a method of a future?

Sean's request suggests just that: https://code.google.com/p/dart/issues/detail?id=10119
 
Because it creates a dependency on the timer?

I could be wrong but I think that dependency is manageable. Both the VM and the browser have ways of accessing time, so it should be doable.
 

Today I saw this code from Task.js:

spawn(function*() {
    var data = yield $.ajax(url);
    $('#result').html(data);
    var status = $('#status').html('Download complete.');
    yield status.fadeIn().promise();
    yield sleep(2000);
    status.fadeOut();
});

How is this done in Dart?

Dart does not have yield, so you'd have to do the CPS transformation yourself. In Dart, the above would look something like like:

$.ajax(url).then((data) {
  $('#result').html(data);
  var status = $('#status').html('Download complete.');
  return status.fadeIn();
}).then((_) {
  return sleep(2000);
}).then((_) {
  status.fadeOut();
});
 

I like the select statement from Go. I kind of expected it in Dart,
why isn't it?

Go has blocking concurrency and fibers (goroutines). The browser is single-threaded so that style of concurrency doesn't work. Without blocking concurrency, there's nothing useful that a select statement could do. (For what it's worth, I really like Go's concurrency model but we're limited by having to compile to JS on the browser.)

Cheers,

- bob

jm

unread,
Apr 26, 2013, 3:33:32 PM4/26/13
to Dart Discussion


Thanks for the kind reply.

> > I like the select statement from Go. I kind of expected it in Dart,
> > why isn't it?
>
> Go has blocking concurrency and fibers (goroutines). The browser is
> single-threaded so that style of concurrency doesn't work. Without blocking
> concurrency, there's nothing useful that a select statement could do.
>

I see, the "select" has already taken place when Dart gets its turn.

--

Regarding your example code, which is broadly equivalent to:

promise = data
.then( (yield)=>step1(yield) )
.then( (_) { sleep(2000); } )
.then( (yield)=>step2(yield,1,2,3) );

Can't this be sugared into:

promise = data
<- step1()
<- { sleep(2000); }
<- step2(1,2,3);

Which is similar to Unix piping. The reversed direction of the arrow
hints at the underlying dependencies of the futures.

Note: *yield* would be in scope within literal function bodies at the
righthand side of the <- "eventually"-operator. It is initialized with
the result of the lefthand side and modified (only) by a return
statement.

I have no experience _at all_ with CPS, but this seems like a possibly
important idiom.
Then again, maybe it's just fool's gold.


Reply all
Reply to author
Forward
0 new messages