Reputation: 437
Having the following code:
Future<String> checkPrinter() async {
await new Future.delayed(const Duration(seconds: 3));
return Future.value("Ok");
}
String getPrinterStatus() {
checkPrinter().then((value) {
return 'The printer answered: $value';
}).catchError((_) {
return "Printer does not respond!";
});
}
void main() {
print(getPrinterStatus());
}
The output is "null" because the function getPrinterStatus() returns without waiting for checkPrinter to complete (correctly i have a warning telling me that getPrinterStatus does not return a string).
What should i do to make getPrinterStatus to wait for checkPrinter()?
Upvotes: 2
Views: 824
Reputation: 31209
There are no such way to make async code to run in a synchronous way in Dart. So you need to make it so async methods returns a Future
so it is possible to await the answer.
The problem you have in your code is your are using the then
method but does not take into account that this method returns a Future
you should return. So e.g.:
String getPrinterStatus() {
checkPrinter().then((value) {
return 'The printer answered: $value';
}).catchError((_){
return "Printer does not respond!";});
}
The two return statements in this example are used for the method your are giving as argument for then()
and are therefore not used to return from getPrinterStatus()
.
Instead, then()
returns a Future<String>
which will complete with the value.
So you need to carry the async
through your program. Your code could make use of some language features you gets from marking a method async
so I have tried to rewrite your code so it works as expected and make use of this features:
Future<String> checkPrinter() async {
await Future.delayed(const Duration(seconds: 3));
return "Ok";
}
// Just an example that the method could be written like this.
// Future.delayed takes a computation as argument.
Future<String> checkPrinterShorter() =>
Future.delayed(const Duration(seconds: 3), () => 'Ok');
Future<String> getPrinterStatus() async {
try {
return 'The printer answered: ${await checkPrinter()}';
} catch (_) {
return "Printer does not respond!";
}
}
Future<void> main() async {
print(await getPrinterStatus());
}
There are some changes I think you should notice:
If a method is marked as async
the returned value will automatically be packed into a Future<Type>
so you don't need to return Future.value("Ok")
but can just return Ok
.
If a method is marked as async
you can use await
instead of using then()
. Also, you can use normal exception handling so I have rewritten getPrinterStatus
to do that.
Upvotes: 0
Reputation: 34180
Future<String> getPrinterStatus() async {
await checkPrinter().then((value) {
return 'The printer answered: $value';
}).catchError((_){
return "Printer does not respond!";});
}
Upvotes: 1
Reputation: 784
Your getPrinterStatus()
is not async
. main()
function will never wait for it's execution.
Make it async
. Refactor your main()
for something like
void main() {
getPrinterStatus().then((value) {
print(value);
}).catchError((_){
return "Printer does not respond!";});
}
Upvotes: 0