Search code examples
dartevent-loopdart-async

Dart event queue and microtask


i am trying to understand, how dart event loop works. I read the event loop article from the website The Event Loop and Dart and the author explain pretty good how event loop in dart works.

But what i don't understand is, how event get queue. For example

new Future(() => 21)
    .then((v) => v*2)
    .then((v) => print(v));

Will here dart gonna create three entries in the event queue or just one? I know, that the class Future is responsible for delay execution and when i create an object from it like

new Future(() => 21)

it will be just one entry in the event loop.

In this article, that i have mentioned above, i read about microtask. This microtask is going to execute before event queue, but i don't see any sense, why dart team implement this microtask? Maybe i need some example!


Solution

  • After some investigation it appears that the right answer is "they will be executed in the next event loop"

    To test it you can write something like this:

    import "dart:async";
    void main() {
      new Future(() {
        scheduleMicrotask(()=>print("before loop 1"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(()=>print("before loop 2"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(()=>print("before loop 3"));
        print("in event loop");
      });
    }
    

    it should output:

    in event loop
    in event loop
    in event loop
    before loop 1
    before loop 2
    before loop 3

    Although i'm not sure that you can't break this optimization. So only sure fact is that the firstFuture will complete first and the second - second.

    EDIT: The strange part(Obsolete):

    With code like this:

    import "dart:async";
    void main() {
      new Future(() {
        scheduleMicrotask(print("before loop 1"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(print("before loop 2"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(print("before loop 3"));
        print("in event loop");
      });
    }
    

    output is:

    before loop 1
    in event loop
    before loop 2
    in event loop
    before loop 3
    in event loop
    Unhandled exception:
    The null object does not have a method 'call'.
    
    NoSuchMethodError: method not found: 'call'
    Receiver: null
    ...
    

    But with this:

    import "dart:async";
    void main() {
      new Future(() {
        scheduleMicrotask(()=>print("before loop 1"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(()=>print("before loop 2"));
        print("in event loop");
      }).then((_) {
        scheduleMicrotask(()=>print("before loop 3"));
        print("in event loop");
      });
    }
    

    output is:

    in event loop
    in event loop
    in event loop
    before loop 1
    before loop 2
    before loop 3

    EDIT2:

    I think i got it. In the first(wrong version) scheduleMicrotask actually never got properly scheduled, but since Dart has eager argument execution it executes print() anyway. So what happens is that all Future getting executed in the next event loop and print all text. That's why output is in call order:

    before loop 1
    in event loop
    before loop 2
    in event loop
    before loop 3
    in event loop

    and not in the schedule order.