Home > database >  What are possible outputs of this dart code
What are possible outputs of this dart code

Time:10-20

Consider the following Dart code:

main() {
  
  var myFuture = Future(
      (){
        print("Executing Future"); 
        return 10;
      }
  );
  print("Exiting main now");
}

It produces the following output:

Exiting main now
Executing Future

My understanding of Dart code execution is that the app executes in an isolate with a single thread (called an event loop). This event loop processes events sequentially as they arrive. The creation of the Future in the above code just puts a new event into the event pipeline, which the event loop picks up for processing after it is done processing the current event (which is the execution of main).

This means that there is absolutely no possibility that the order of the lines in the output would be reversed. I mean, it is guaranteed 100% that the above program will NEVER print this:

Executing Future
Exiting main now

Is my understanding correct?

CodePudding user response:

You should, in general, not write code like this where you are dependent on the order which async events are being executed. If you are depending on something to happen, you should await the dependent futures to get values.

The reason is that your code does execute in the order you describes. But we could also have made a Future.sync which changes how the same program is executed (not really surprising based on the name of that constructor):

void main() {
  final myFuture = Future.sync(() {
    print("Executing Future");
    return 10;
  });
  print("Exiting main now");
}

// Returns:
// Executing Future
// Exiting main now

You cannot really see how much code is being executed before a Future is returned to your calling code. Which is a major reason why you should never depend of execution order when it comes to asynchronously code besides awaiting on needed futures/streams to get a value.

But yeah, if this is just a theoretical question, you are right about how things works and your specific code would always be executed like you are saying based on the API description of the Future constructor:

Creates a future containing the result of calling computation asynchronously with Timer.run.

https://api.dart.dev/stable/2.14.4/dart-async/Future/Future.html

I can in general recommend the following article about the event loops in Dart:

https://medium.com/dartlang/dart-asynchronous-programming-isolates-and-event-loops-bffc3e296a6a

UPDATE 1

The reason why I am saying:

You cannot really see how much code is being executed before a Future is returned to your calling code.

Is because we can do something like this:

import 'dart:async';

void main() {
  print('Step 1');
  myAsyncMethod().then(print);
  print('Step 3');
}

Future<String> myAsyncMethod() async {
  print('Step 2');
  await Future.delayed(const Duration(milliseconds: 1), () => null);
  return 'Step 4';
}

Which will output:

Step 1
Step 2
Step 3
Step 4

The reason for this behavior is because async methods will run as a sync method until the first await operation where it will then afterwards behave like an async function. So when we call myAsyncMethod we are right away executing print('Step 2') but then we go back and executes print('Step 3').

So if we just look at:

myAsyncMethod().then(print);

We don't really know what have been executed before we got the Future. It should also be noted that this is not unique to async marked method. We could also have done the following which returns the same output:

import 'dart:async';

void main() {
  print('Step 1');
  myAsyncMethod().then(print);
  print('Step 3');
}

Future<String> myAsyncMethod() {
  final completer = Completer<String>();
  print('Step 2');
  Future.delayed(
    const Duration(milliseconds: 1),
    () => completer.complete('Step 4'),
  );
  return completer.future;
}
  •  Tags:  
  • dart
  • Related