C#5 async return types -clarification? - .net-4.5

From here :
Async methods can return Task<T>, Task, or void.
Why return Task<T> or Task? Because they're awaitable, and void is
not. So if you have an async method returning Task<T> or Task, then
you can pass the result to await.
Now consider this example :
/*1*/ public async Task<int> CalculateAnswer()
/*2*/ {
/*3*/ await Task.Delay(100);
/*4*/
/*5*/ // Return a type of "int", not "Task<int>"
/*6*/ return 42;
/*7*/ }
I do understand that the moment the control enters the async method and meets the await operator , it first check to see if the awaitable has finished , if it has then it runs regular(sync). and if it didn't , it returns from the async method.
Ok so it returns and we need to keep an eye on the async task. and I guess thats why we have Task<T> at the method signature.
Question
But Why do I need int in the Task<int> ? the awaitable has nothing(!) to do with INT !! -- it could be a webservice downloading something. in order to keep an eye on the async operation i could use Task only.
So Either the Task<t> is there to keep an eye for the async operation OR(!!!) is it there to indicate the return value of the method ?
I'm confused. :-(

There are two tasks in this example.
The task returned by CalculateAnswer is a Task<int>. It represents the method CalculateAnswer. That task will complete when CalculateAnswer completes, and its result (an int) will be the return value of that method.
The other task is the one returned by Task.Delay. That one is just a Task; there's no result value. That task represents the delay.

Related

How to test a void function in Dart?

I am new to unit tests in Dart/Flutter and I would like to write a test for a void function. When functions return something I am writing a test like this:
test('Gets user save', () async {
final userSave = await mockSource!.getUserSave();
expect(userSave!.age, equals(20));
});
In such a scenario like above expect can be used since getUserSave function returns a user model.
How about checking if test passes of fails for a void/Future function like below? I can not use expect because it does not return a value.
Future<void> clearUserSave() async {
DatabaseClient mockDBClient = MockDatabaseClientImpl();
mockDBClient.clear();
}
I use flutter_test and mockito for testing.
Typically a void function will produce a side effect of some sort. When writing a test for a void function, I would check whatever state is effected by the void function before and after calling the function to be sure that the desired side effect has occurred.
In this specific case, you are calling clear on a DatabaseClient. I don't know the specifics of the DatabaseClient api, but I would construct a test where the client contains some data before calling clear, and then check that the data is no longer there after calling clear.
Something along the lines of this:
Future<void> clearUserSave() async {
DatabaseClient mockDBClient = MockDatabaseClientImpl();
mockDBClient.add(SOMEDATA);
expect(mockDBClient.hasData, true);
mockDBClient.clear();
expect(mockDBClient.hasData, false);
}
you can add nullable variable and assign variable value in method, after call method check if this varaible isNotNull
like this:
test('Gets user save', () async {
await mockSource?.getUserSave();
final userSave=mockSource.user;
expect(userSave,isNotNull );
});
testing a function that return void :
expect(
() async => await functionThatReturnsVoid(),
isA<void>(),
);

Does a function that calls a Future needs to be a Future too?

I have a function that calls a Future in it. Now I am not sure if the first function needs to be a future too to await for the data. Here is my code:
FireBaseHandler handler = FireBaseHandler();
saveRows() {
handler.saveRows(plan.planId, plan.rows); ///this is a future
}
In my FireBaseHandler class I have this Future:
final CollectionReference usersCol =
FirebaseFirestore.instance.collection('users');
Future saveRows(String id, data) async {
return await usersCol.doc(myUser.uid).collection('plans').doc(id)
.update({'rows': data});
}
So does the first function needs to be a Future too?
You can have async function inside a sync function. But this way you lose ability to await for the result. And await is allowed only in functions marked as async, which leads us to Future as a the result of that function. So, yes, if you need to wait for the result, both functions have to be Future functions.
Edit:
If you need your wrapper function to be sync, but still be able to retrieve the result from inner async function, you can use a callback:
saveRows(Function(dynamic) callback) {
handler.saveRows(plan.planId, plan.rows).then((result){
callback(result);
});
}
This way the result will be retrieved at any point of time after calling the function (the code is not awaited)

Flutter Getx Get.back() not returning value when used along with async function

I am using Getx package and I want to return a value using Get.back(result: getPhoneNumber()). But Get.back() does not work if an async function is executed before it. Below is the code snippet where handleResponse() is an async function. In addition to this, I have added a print statement to check the value of isSuccessful variable. the value it returns is true.
handleResponse async function:
In addition to this, I would like to state that when I comment the ResponseHandler().handleResponse() function, it works fine as expected.
What happens here is that the back() method seems to finish while getPhoneNumber() is yet to finish. The value passed in return is nullable, and most likely gets a null value since getPhoneNumber() is yet to finish.
What you can do here is first fetch the value from getPhoneNumber() before calling back().
var phoneNumber = await getPhoneNumber();
if(isSuccessful && phoneNumber != null){
Get.back(result: phoneNumber);
}

While the inner method async does the outer method has to be async?

I have an async method. Can I call it from an non-async method? Like the following
My method
void method() async{
await 'something'
}
Case 1
onPressed:() {
method();
}
Case 2
onPressed:() async{
await method();
}
Which of the above is correct? It seems to me two of them is OK. However, the second one I think works much more slower, am I wrong?
In general, the caller of an async function must also be asynchronous if it wants to wait for the call to complete. This makes asynchronous-ness contagious.
In your case, your async function is a "fire-and-forget" function; callers cannot wait for it to complete, so it doesn't matter. Your second case (with await method()) is wrong because you should use await only on Future/FutureOr, but method returns void, so there nothing to wait for. (The Dart analyzer would warn you about this if you have the await_only_futures lint enabled.)
You also could simplify your code further by using a tear-off instead of creating an unnecessary closure:
onPressed: method

Why async keyword function without await keyword in Dart?

I saw many people's code use async keyword in a function without an await keyword in the function body. Even some official flutter example code do this. I have no idea why. What is the point? Is this a mistake or having a purpose?
Normally, I just remove the async keyword from those code and everything will run without any problems. Can some dart expert clarify that if there is a purpose for a function which has the async keyword but NO await keyword? Or is this just their mistake?
async is sometimes used to simplify code.
Here are some examples:
Future<int> f1() async => 1;
Future<int> f1() => Future.value(1);
Future<void> f2() async {
throw Error();
}
Future<void> f2() {
return Future.error(Error());
}
According to official Dart Language tour, async executes synchronously until it finds await keyword :
Note: Although an async function might perform time-consuming operations, it doesn’t wait for those operations. Instead, the async function executes only until it encounters its first await expression (details). Then it returns a Future object, resuming execution only after the await expression completes.