Understanding asynchronous and synchronous in Dart - flutter

We know that in Dart everything runs synchronously and according to some definition I found on internet
When you execute something synchronously, you wait for it to finish before moving on to another task. When you execute something asynchronously, you can move on to another task before it finishes.
What I don't understand here is that why b is printed before c I mean if code is running synchronously then it should wait for completion of line 2 to print c and only after printing c
It should print b
Ps- I know I can use async and await keywords to wait for line 2 to complete it's execution. I just want to understand how this synchronous code works.
void main(){
print("a");
Future.delayed(Duration(seconds:
5),(){
print("c");
});
print("b");
}
Output- a
b
c

When you write :
print("a");
Future.delayed(Duration(seconds: 5),(){
print("c");
});
print("b");
You tell the program to print "a", then to launch a Future that will resolve in 5 seconds and print "c", then to print "b"; but you never tell the program to wait for the Future to complete.
Which is synchronous.
And this is why you must use await keyword to make the program wait for the Future completion before moving to next instruction.

No not really. It would only print c before b if you use the await keyword. This keyword tells Dart to wait till this future is complete and then move on to the next task.
For example
void main() async {
print("a");
//await tells dart to wait till this completes. If it's not used before a future, then dart doesn't wait till the future is completed and executes the next tasks/code.
await Future.delayed(Duration(seconds:
5),(){
print("c");
});
print("b");
}
Output
Output- a
c
b

Related

What is the purpose of awaiting the empty Future in this animation code?

I was going though GSkinner's flutter_vignattes codebase, in one of the functions there was an empty await for a Future
Future<void> _reset() async {
// Wait until next event loop to advance animation and call setState or flutter will yell at you
await Future<void>.value();
_controller.forward(from: 1.0 - _percentage * 0.83);
if (_isLoading) {
setState(() {
_model = BasketballGameModel.randomize();
});
}
_isLoading = false;
}
I understand how promises are sent to micro-task queue in JS (assuming same happens in Dart), but not quite able to understand the reason provided in the comment here i.e.,
// Wait until next event loop to advance animation and call setState or flutter will yell at you
Really appreciate if someone can provide a deeper insight into this. This is the particular line in codebase i am referring to.
https://github.com/gskinnerTeam/flutter_vignettes/blob/0ccc72c5b87b5ab6ba2dee9eff76f48ce2fadec8/vignettes/basketball_ptr/lib/demo.dart#L149
Future<void> function() {}
Defines an asynchronous function that ultimately returns nothing but can notify callers when it eventually completes. Also see: What's the difference between returning void vs returning Future?
Or You can learn from this https://github.com/dart-lang/sdk/issues/33415

Futures aren't finishing in queue

I build a queue of futures to ensure that those futures get completed in a sequential order, because even if one async function is called before the other this won't ensure that they get executed in this order when pushed on the event loop (my assumption).
In the UI there is a button, every time it gets pressed the async computation is pushed onto this queue. When pressed in a way that the async computation is finished before the next button press there isn't a problem but when pressed fast multiple times the computation won't finish.
In the example below every computation after job 1 won't finish.
int i = 0;
class TouchlessAlarmScheduleQueue {
Future _future = Future(() {});
addJob(String alarmId, Future<void> Function() job) {
print('$i added');
int iCopy = i;
_future = _future.then((_) {
print("$iCopy done");
return job();
});
i++;
}
}
Console Output:
flutter: 0 added
flutter: 0 done
flutter: 1 added
flutter: 2 added
flutter: 1 done
[VERBOSE-2:profiler_metrics_ios.mm(203)] Error retrieving thread information: (os/kern) invalid argument
Not sure if this profiler output is related to the problem.
Worked just fine here:
You should probably only use async/await for clarity. I have done the same thing before. I use an improved version in oun production app: https://twitter.com/gazialankus/status/1364695537585381378

misleading concept of future and async programming in flutter

I found it a bit confused with the concept of Future and async programming.
By definition, Future is a type that async function will return in Future.
The purpose is that we want the program to keep running while it is still waiting for the result of the async function.
What I dont understand is that, every often/always, I saw people using async with await which stop proceeding the program until it gets the result from async function called.
Arent we come to full circle? At first, async comes in for the situation that we dont want to wait for program taking time. But now, we use async with await in which we wait until the result is there
It is not always necessary to use await with a future. await can be used if you want to do further processing with the data.
Example:
Future<int> _getInt()async{
Future.delay(Duration(seconds:3)); //simulating network delay
return 7;
}
void _add() async{
int res = await _getInt() + 10; //need to await because we are going to use a future variable
_putInt(res); //not nesscary to await if you don't want to handle the response
/* Ex: var result = await _putInt(); // if you want to handel the response
if (result.statusCode==200){
// handle success
}else{
// handle error
}*/
}
Future _putInt(int number)async{
var res = await http.post('url',body:{'data':number});
return res;
}
Well, your institution is right, we use Future and async as it is nonblocking and follows an event loop approach, meaning there is a callback to the Future when it is ready to execute.
Coming to your point, I have done this myself a lot of time. And neither approach is wrong.
But when it comes to Flutter, it is in your best interest that you don't do anything else when running an async function because dart is single-threaded.
This can be blocking sometimes depending on the work of the function.
This can also be simply for UX as some data would be critical to your application and you shouldn't allow the user to do anything else until it is loaded.

Future<void> async vs simply void async in Dart

In Dart,
what is the difference between saying
Future<void> doStuff() async { ...
and
void doStuff() async { ...
I know what a Future<T> is and how async/await work generally, but I never realized Future<void> was a thing. I have some code that has the Future<void> all over the place and I want to replace it with my normal way of doing things, but I don't want to break anything.
Notice that both functions use async. The question is NOT 'what is the difference between async and non-async functions?' or 'can you give a brief attempt at explaining asynchronous programming in Dart, please?'
I'm aware that there is a pretty much identical question already, but if you look closely at the answers you will see nobody actually answered the question in a clear way -- what is the difference? Is there any difference? Is there no difference?
To elaborate, consider the following two functions:
// notice there is no warning about not returning anything
Future<void> futureVoid() async {
await Future.delayed(Duration(seconds: 2), () {
var time = DateTime.now().toString();
print('$time : delay elapsed');
});
}
void nonFutureVoid() async {
await Future.delayed(Duration(seconds: 2), () {
var time = DateTime.now().toString();
print('$time : delay elapsed');
});
}
Then test them with a button whose onPressed() function is:
onPressed: () async {
await nonFutureVoid(); // notce that this await *DOES* delay execution of the proceeding lines.
var time = DateTime.now().toString();
print('$time : <-- executed after await statement');
}
Log result:
flutter: 2021-02-23 21:46:07.436496 : delay elapsed
flutter: 2021-02-23 21:46:07.437278 : <-- executed after await statement
As you can see, they both behave exactly the same way -- the simple void async version IS awaited. So what is the difference?
With your edit, your question makes more sense. Your question is really about principle vs. practice.
In principle, a function that returns void is different from a function that returns Future<void>. One conceptually represents something that does not return anything, and the other represents an asynchronous computation that can fire callbacks when it completes.
In principle, you should never attempt to use the value returned from a void function. It doesn't make sense. If you run the Dart analyzer against code that does await nonFutureVoid(); you'll get a warning if the await_only_futures lint is enabled.
In practice, there are cases where attempting to use a void return value happens to not generate an error. Those are quirks in the language (or bugs in the implementation); you should not rely on them. (Dart didn't originally have a void return type. When it was added later, it wasn't implemented to mean "no value" but instead to mean "a value that you aren't allowed to use". See Dart 2: Legacy of the void. Normally that subtle difference shouldn't matter.)
Being able to do await nonFutureVoid(); is a bug1, and it seems that that bug is now fixed: await nonFutureVoid(); is an error if you use Dart 2.12 or later and enable null-safety and the stricter type-checking that comes with it.
You can observe the old and new behaviors with DartPad by toggling the "Null Safety" button: https://dartpad.dartlang.org/b0dae0d5a50e302d26d93f2db3fa6207
1 There are a lot of issues filed on GitHub with a lot of back-and-forth discussion, so yes, it is rather confusing. Most people seemed to agree that allowing await void was undesirable, however.
A void function indicates that the function returns nothing, which means you can not act on the result of that Function (and cannot await on it's result).
Meanwhile, the Future<void> function returns a Future object (that has value of void). If you don't have a return statement, a missing_return warning will show up (it can still be compiled). You can still act on that result by awaiting it, but cannot actually use the value because it's void.
While it seems like it'd be just fine with whatever you are using, I think it's better to use Future for every async function for type-safety and better maintenance.

How do I make a Stream version of Future.wait in Dart?

I want to run Future.wait() on some network calls so they can run concurrently. I want to speed this up even further my returning the results as they become available so I can start displaying them. I figured just a small modification to the Future.wait call would be all I need, but unfortunately, it uses private classes internally. Is there a better way to accomplish this?
Future.wait dart documentation
You can use Stream.fromFutures constructor
The stream reports the results of the futures on the stream in the
order in which the futures complete. Each future provides either a
data event or an error event, depending on how the future completes.
If some futures have already completed when Stream.fromFutures is
called, their results will be emitted in some unspecified order.
When all futures have completed, the stream is closed.
Stream<int> streamingInts = Stream.fromFutures([
Future.delayed(Duration(seconds: 1), () => 1),
Future.delayed(Duration(seconds: 2), () => 2),
]);
await for (final i in streamingInts) {
print(i);
}
My real use case - to show that loading takes more time than expected
if my real api call ends fast I just yield LoadedState & stop listen to stream
if my real api call is too slow special Future.delayed will fire special state LoadingTakesTooLongState
Stream<BlocState> loadingStates = Stream.fromFutures([
Future.delayed(_kTooSlowDelay, () => LoadingTakesTooLongState()),
_loadData(),
]);
await for (var state in loadingStates) {
yield state;
if (state is LoadedState) break;
}
Future<LoadedState> _loadData() ...