Home > Back-end >  How is the order of callbacks scheduled?
How is the order of callbacks scheduled?

Time:06-22

I'd like to kick off an HttpRequest and then poll for its completion. This feels like a fairly common pattern.

void main() {
  _tick(0);
  _tickB(0);
  build();
  print("End of main");
}

void build() {
  var path = '../layout.txt';
  html.HttpRequest.getString(path).then((String layout) {
    print("layout received");
  });
}

void _tick(int i) {
  print("A $i");

  if (i < 10) incr(i).then(_tick);
}

void _tickB(int i) {
  print("B $i");

  if (i < 10) incr(i).then(_tickB);
}

Future<int> incr(int i) async {
  i  ;
  return i;
}

Output:

A1
B1
End of main
A2
B2
A3
B3
A4
B4
A5
B5
layout received

I would expect to see "layout received" appear interleaved with the other callbacks when the HttpRequest completes but its not. Its always (no matter the value of i, 5 is just a demo number) at the end of the interleaved callbacks.

Why is this? How can I schedule the build callback in such a way that it completes during the other callback chains?

CodePudding user response:

Your incr function doesn't actually do any asynchronous work. incr will be executed to completion immediately. Since the returned Future is already complete, its Future.then callbacks then will be scheduled in the microtask queue. Only after the microtask queue is empty will the separate event queue be processed. Your _tick/_tickB functions therefore create a (temporary) live-lock situation by repeatedly adding events to the microtask queue and preventing your HttpRequest Future from completing.

You can get the behavior you expect by making incr do some asynchronous work:

Future<int> incr(int i) async {
  await Future.delayed(Duration.zero);
  i  ;
  return i;
}

and then your output will be:

A 0
B 0
End of main
A 1
B 1
layout received
A 2
B 2
A 3
B 3
...

Further reading: The Event Loop and Dart

  • Related