How to call and wait async function done inside sync function in flutter - flutter

I want to call and wait async function done before return from a sync function
// async function
Future<User> getUser(String username) async {
...
}
In dart, i could use https://api.dart.dev/stable/2.9.2/dart-cli/waitFor.html to wait a async function before go to next statement.
bool checkUser(String username, String encodedPwd) {
var user = waitFor<User>(getUser(username));
if (user.pwd == encodedPwd)
return true;
else
return false;
}
Because the require of the framework, the checkUser function will be call by framework, and must be a sync function.
In flutter, I could not use dart:cli, I implement by pattern .then() .whenComplete(), but when call checkUser the statement print(1) will be call and end the function without wait for getUser finish.
bool checkUser(String username, String pwd) {
getUser(username).then((user) {
if (user.pwd == encodePwd(pwd)) {
return true;
} else {
return false;
}
);
print(1);
}
My question is how to call async function inside sync function and wait the async function done before return.
Thank you.

Being able to do what you ask would basically render the distinction between sync and async functions useless (and block the main thread I think). The function you linked "should be considered a last resort".
I think what you want is :
Future<bool> checkUser(String username, String pwd) async {
var user = await getUser(username);
return user.pwd == encodePwd(pwd) ? true : false;
}

This can be achieved by creating a task, then waiting/yielding for the task to complete. The Yield prevents blocking.
var result = MyAsyncMethod.InvokeAsync(data);
result.Start();
while (result.Status != TaskStatus.RanToCompletion)
{
System.Threading.Thread.Yield();
}

Related

i have question about asynchronous programming at flutter

void main() async {
check();
print('end');
}
Future check() async {
var version = lookUpVersion();
print(version);
}
int lookUpVersion() {
return 12;
}
void main() async {
check();
print('end');
}
Future check() async {
var verion = await lookUpVersion();
print(version);
}
int lookUpVersion() {
return 12;
}
These two code only have one difference, await keyword.
I wonder that why not did they wait for main function code? even I used Future+async keyword at first code.
Can you explain about this?
The async and await keywords provide a declarative way to define asynchronous functions and use their results.
For first one - result will be
//12
//end
For second one - result will be
//end
//12
Which means if you add await it will become asynchronous.

Run multiple asyn function flutter one after one flutter

hello I want have to run two functions(Function1() and Function2()) and store value of these returns and run third function. But some time according to condition Function1() or Function2() or both not be run.
if(condition1){
await Function1();
}
if(condition2){
await Function2();
}
await Functon3();
I try as above but Function3() run simultaneously with Function1() or with Function2().
My Function1() code looks like following...
Future Function1() async {
apiService
.apiFileUpload()
.then((value) async {
///codes goes here
}).catchError((error) {
print('EEEE: ' + error.toString());
});
}
If anything not clear please let me know in the comment section.
Please do not use .then() in combination with async/await. It is technically possible, but it takes some skill to get it right, so why make it hard on yourself. Stick with one way of doing it, use either one or the other. You mixed it up and through a slight oversight, your Function1 does not actually wait on it's result. It just returns, with the function still running in the then block. So you await it, but that does not help.
Since you are using await already, stick with that and remove .then() from your repertoire for now:
Future Function1() async {
try {
final value = await apiService.apiFileUpload();
///codes goes here
} catch(error) {
print('EEEE: ' + error.toString());
}
}
You can use await
Future Function1() async {
try{
final value = await apiService
.apiFileUpload();
final value2 = await secondFuntion();
///add more and condition on values
} catch(e){
.....
}
}
from your question you need to tell the compiler to stop on particular task with await and avoid using then function it will never stop your compiler
your future fuction:
Future Function1() async {
apiService
.apiFileUpload()
.then((value) async {
///codes goes here
}).catchError((error) {
print('EEEE: ' + error.toString());
});
}
Modified Future func
Future Function1() async {
var result = await apiService.apiFileUpload();
if(result == success){
// code goes here
}else{
//you can show your error here
}
}

dart future method with bool return type always returns false

I am calling class method which is in a different file from the main method of main.dart. Here I am trying to get the session status of the user. I am not sure what I am doing wrong, the return value always returns false when called in from the main method, but returns true if printed out in the actual method.
Here the expected result is true as the user is currently in the system and is signed in.
Here is my main method -
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await Authenticate().getSessionStatus().then((status) => {
print(status)
});
}
Here is my class method -
class Authenticate {
Future<bool> getSessionStatus() async {
bool _isSessionActive = false;
await FirebaseAuth.instance.authStateChanges().listen((User? user) {
if (user == null) {
//print('User is currently signed out!');
_isSessionActive = false;
} else {
//print('User is signed in!');
_isSessionActive = true;
}
});
return _isSessionActive;
}
}
The print statements inside the Authenticate class method, if turned on returns true which is the expected value, but calling the getSessionStatus method from the main method and then printing the value of the status variable always returns false. I believe it has something to do with order in which it is processed, but I am not able to fix it at all.
You can't check if the user is logged with FirebaseAuth.instance.authStateChanges(), since this method only notifies when the user status changes.
You can use the FirebaseAuth.instance.currentUser property instead:
class Authenticate {
Future<bool> getSessionStatus() async {
return FirebaseAuth.instance?.currentUser != null;
}
}
You cannot await the StreamSubscription (which the compiler should warn you about) returned by FirebaseAuth.instance.authStateChanges().listen(...). Below is a minimal example to illustrate what is happening.
void main() async {
bool test = await awaitMe();
print('Main received:' + test.toString());
}
Future<bool> awaitMe() async {
bool innerVal = false;
print('start');
await streamMe().listen((val) {
print('Listener received: ' + val.toString());
innerVal = true;
});
print('end');
return innerVal;
}
Stream<bool> streamMe () async* {
yield true;
}
This will print:
start
end
Main received:false
Listener received: true
So you are actually not awaiting anything.

Dart Flutter, help me understand futures

See this code:
class SomeClass{
String someVariable;
SomeClass();
Future<String> getData () async {
Response response = await get('http://somewebsite.com/api/content');
Map map = jsonDecode(response.body); // do not worry about statuscode, trying to keep it minimal
someVariable = map['firstName'];
return 'This is the first name : $someVariable';
}
}
Now look at main:
void main(){
String someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData().then((value) => value);
return firstNameDeclaration;
}
}
When working with Future, like in the case of firstNameDeclaration why do I have to use .then() method to access the string object, since I am waiting for the function to finish?
When searching on the web, some people use .then() others don't, I am confused.
Kindly help me have a clearer understanding of how Futures and async functions overall work.
Background
Asynchronous operations let your program complete work while waiting for another operation to finish. Here are some common asynchronous operations:
Fetching data over a network.
Writing to a database.
Reading data from a file.
To perform asynchronous operations in Dart, you can use the Future class and the async and await keywords.
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
Futures vs async-await
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
async-await is just a a declarative way to define asynchronous functions and use their results into Future and it provides syntactic sugar that help you write clean code involving Futures.
Consider this dart code snipped involving Futures -
Future<String> getData(int number) {
return Future.delayed(Duration(seconds: 1), () {
return 'this is a future string $number.';
});
}
main(){
getData(10).then((data) => {
print(data)
});
}
As you can see when you use Futures, you can use then callback when the function return a future value. This is easy to manage if there is single "then" callback but the situation escalates quickly as soon as there are many nested "then" callbacks for example -
Future<String> getProductCostForUser() {
return getUser().then((user) => {
var uid = user.id;
return getOrder(uid).then((order) => {
var pid = order.productId;
return getProduct(pid).then((product) => {
return product.totalCost;
});
});
});
}
main(){
getProductCostForUser().then((cost) => {
print(cost);
});
}
As you can when there multiple chained "then" callback the code become very hard to read and manage. This problem is solved by "async-await". Above chained "then" callbacks can be simplified by using "async-await" like so -
Future<String> getProductCostForUser() async {
var user = await getUser();
var order = await getOrder(user.uid);
var product = await getProduct(order.productId);
return product.totalCost;
}
main() async {
var cost = await getProductCostForUser();
print(cost);
}
As you can above code is much more readable and easy to understand when there are chained "then" callbacks.
I hope this explains some basic concepts and understanding regarding the "async-await" and Futures.
You can further read about topic and examples here
Basically, you should either use await OR then(). However, Dart guidelines advocates that you should prefer use await over then() :
This code :
Future<int> countActivePlayers(String teamName) {
return downloadTeam(teamName).then((team) {
if (team == null) return Future.value(0);
return team.roster.then((players) {
return players.where((player) => player.isActive).length;
});
}).catchError((e) {
log.error(e);
return 0;
});
}
should be replaced by :
Future<int> countActivePlayers(String teamName) async {
try {
var team = await downloadTeam(teamName);
if (team == null) return 0;
var players = await team.roster;
return players.where((player) => player.isActive).length;
} catch (e) {
log.error(e);
return 0;
}
}
In your case, you should write :
void main(){
Future<String> someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData();
return firstNameDeclaration;
// Or directly : return await instance.getData();
// Or : return instance.getData();
}
}

Dart Completer.complete() results never resolve

I have a function that returns a future which depends on the result of a callback to resolve:
Future connectSocket(String email, String password, {Function onConnectCallback}) async {
var completer = new Completer();
print("Connecting...");
var query = getQueryString(email, password);
socketIO = await SocketIOManager().createInstance(SocketOptions(localDomainWindows, query: query));
socketIO.on("loginError", (data) {
print("Login err");
_connected = false;
connectedCallback();
completer.complete(false);
});
socketIO.onConnect((data) {
print("***CONNECTED***");
_connected = true;
completer.complete(true);
connectedCallback();
});
socketIO.connect();
return completer.future;
}
I can see ***CONNECTED*** printed to the console, and my socket server acknowledges the connection, but the function await-ing the resolution never resumes, it just hangs.
socketConnection.connectSocket(_email, _password)
.then((success) {
print("SUCCESS") // never gets printed
}
The only possible explanation for this is that some code in the callback is blocking your program from continuing because Completer.complete should otherwise always make the future complete.
If it is blocked, however, the event loop will never be able to call your code.
As a bool assignment should never be blocking (_connected = true;), the only part of your function that could be halting your program is connectedCallack();. If you remove or fix it, you should see your future complete.