I have a few basic questions about Dart Futures
that I can't seem to get an answer to myself. Considering the following code:
Future(
() => print('from Future') // 1
).then(
(_) => print('after Future') // 2
);
Future.delayed(someDuration, () => print('after Future'));
What would the use case be? Like to split a longer 'task' so that other code is run in between? Is it something that is actually done in practice, like in Flutter, to prevent 'jank'?
Edit: I found a very insightful article: https://webdev-angular3-dartlang-org.firebaseapp.com/articles/performance/event-loop#how-to-schedule-a-task, which kind of answers pretty much every single question I asked here.
The constructor you are calling is Future()
which are documented as:
Creates a future containing the result of calling
computation
asynchronously with Timer.run.If the result of executing
computation
throws, the returned future is completed with the error.If the returned value is itself a Future, completion of the created future will wait until the returned future completes, and will then complete with the same result.
If a non-future value is returned, the returned future is completed with that value.
https://api.dart.dev/stable/2.8.2/dart-async/Future/Future.html
Where Timer.run
is documented as:
Runs the given
callback
asynchronously as soon as possible.This function is equivalent to
new Timer(Duration.zero, callback)
.
https://api.dart.dev/stable/2.8.2/dart-async/Timer/run.html
So, since we are creating a timer which are already completed, it will immediately be put on the event loop.
So with this knowledge we can answer your questions:
Block 1 is put on the event loop. Since block 2 is dependent on the result from block 1, it will not be put on any queue. Instead, block 2 will be notified when block 1 has returned its result.
As far as I understand the documentation, block 2 will be executed immediately synchronously as part of the block 1 is completed (unless the future as has already been completed which then will trigger a microtask):
Register callbacks to be called when this future completes.
When this future completes with a value, the onValue callback will be called with that value. If this future is already completed, the callback will not be called immediately, but will be scheduled in a later microtask.
https://api.dart.dev/stable/2.8.2/dart-async/Future/then.html
The specific example does not make much sense. But yes, you can use the Future.delayed
if you want to schedule smaller tasks on the event loop. It should be noted that Dart are single threaded so you cannot schedule tasks to be running in another thread by using Future.delayed
.
But in the context of Flutter, you properly want to have multiple smaller tasks so the UI can be drawn between each task. But if you are going to make some heavy calculations, you should properly use an Isolate
to run these in another thread.