Dart await removes then? - dart

Do await remove "then"?
Why is it that when using then in the following is causing this error:
// Error: [dart] The method 'then' isn't defined for the class 'String'. [undefined_method]
Modified code from here
import 'dart:async';
Future<void> printDailyNewsDigest() async {
var newsDigest = await gatherNewsReports();
// Error: [dart] The method 'then' isn't defined for the class 'String'. [undefined_method]
newsDigest.then(print);
// print(newsDigest);
}
main() {
printDailyNewsDigest();
printWinningLotteryNumbers();
printWeatherForecast();
printBaseballScore();
}
printWinningLotteryNumbers() {
print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}
printWeatherForecast() {
print("Tomorrow's forecast: 70F, sunny.");
}
printBaseballScore() {
print('Baseball score: Red Sox 10, Yankees 0');
}
const news = '<gathered news goes here>';
const oneSecond = Duration(seconds: 1);
// Imagine that this function is more complex and slow. :)
Future<String> gatherNewsReports() =>
Future.delayed(oneSecond, () => news);

await doesn't "remove" then, but it allows to write async code in a more convenient syntax as with then and kind of replaces then.
await is then rewritten back to then by the compiler.
await postpones the execution of the following code until the result of the awaited async operation is completed and returns the result value.
The result value is not a Future anymore and therefore then() is not available.

Related

Dart, how to unit test a function with mocking method inside

I want to unit test a function with mocking a function inside.
This is the simplified code I want to test:
import 'package:test/test.dart';
Future<int> function() async {
final int value = await API(); // This returns a int.
return value + 1;
}
void main() {
test('test function, (when api() returns 1)', () {
expect(function(), completion(equals(2)));
});
}
When testing, I don't want to call the real API() function but, want to mock it instead. Is there any solution to this?

How do you create a Future in Dart with a lambda/higher-order function and resolve it?

I'm having trouble figuring out a way to do the equivalent of the following Javascript code in Dart:
async function main(){
await new Promise((resolve) => {
setTimeout(resolve, 200);
});
// stuff after 200ms happens here
}
It's nice to be able to create a Promise and resolve it on the fly... can you also do this in dart? I've read about completers, but the examples use "regular" functions, rather than lambda/higher-order ones.
I am not entirely sure what you want but you can write your own example as this in Dart:
import 'dart:async';
Future<void> main() async {
print(DateTime.now().millisecond); // 417
await Future<void>.delayed(const Duration(milliseconds: 200));
print(DateTime.now().millisecond); // 625
}
Maybe a more directly conversion would be:
import 'dart:async';
Future<void> main() async {
print(DateTime.now().millisecond); // 417
await () async {
await Future<void>.delayed(const Duration(milliseconds: 200));
}();
print(DateTime.now().millisecond); // 625
}
The given ECMAScript snippet has an error, setTimeout is supposed to be called on a function, not undefined.
Also, it doesn't really need to be a lambda at all.
function delay_200(resolve) {
setTimeout(resolve, 200);
};
// statically allocated delay function
async function main() {
await new Promise(delay_200);
// stuff after 200ms happens here
}
Now, I haven't used Dart in quite some time, but I think it would be equivalent to the following:
Future<void> main() async {
await Future.delayed(
Duration(milliseconds: 200)
);
// stuff after 200ms happens here
}
Now, I'm honestly not sure if you can construct a Future like you can a Promise, so I didn't really answer the primary question.

flutter async function : _Future<String> returned instead of string value when subfunction is done

Trying to figure a good way to handle nested async functions I'm doing some tests with dartpad. In the following example I don't understand why _Future is printed instead of the value (level1String) ?
The output is :
toto
before await level2
before duration
after duration
13
after level 2
Instance of '_Future' // my concern is here since "after level 2" is printed I should have reached the return statement
after level 1
yeah!
import 'dart:convert';
import "dart:async";
import "dart:html";
void main() async {
print('toto');
await print(level1String());
print('after level 1');
}
Future<String> level1String () async {
print('before await level2');
print(level2String());
print('after level 2');
return 'level1String';
}
int level2String () {
print('before duration');
Timer(Duration(seconds: 3), () {
print('yeah!');
});
print('after duration');
return 13;
}
await print(level1String());
should be
print(await level1String());
level1String() is returning the Future you need to await, not print()

The Fat Arrow is syntactic sugar - but do not return

The Fat Arrow is syntactic sugar, like described here
But if I remove return in(look for: future.then(print); // << Removed return) then it complains about missing return?:
Hmm, or am I missing a "return-return" kind og thing...
import 'dart:async';
main() {
printsome();
print("After should be called first...");
}
Future<void> printsome() {
final future = delayedFunction();
future.then(print); // << Removed return
// You don't *have* to return the future here.
// But if you don't, callers can't await it.
}
const news = '<gathered news goes here>';
const oneSecond = Duration(seconds: 1);
Future<String> delayedFunction() =>
Future.delayed(oneSecond, () => news);
I get this warning:
[dart] This function has a return type of 'Future<void>', but doesn't end with a return statement. [missing_return]
The => expr implicitly returns the result of expr, so if you want to replace it with a function body { return expr; } you need to add return, otherwise null will be implicitly returned.
You declared a function with return type Future<void> and DartAnalyzer warns you that your function is not returning such a value.
You can either add async which makes the function implicitly return a Future
Future<void> printsome() async {
final result = await delayedFunction();
}
or if you don't want to use async you can just add return
Future<void> printsome() {
final future = delayedFunction();
return future.then(print); // return the Future returned by then()
}

How return Future from Future? Or this is prohibited in async library?

How I can return Future value from Future object?
This code does not work.
import 'dart:async';
void main() {
var temp = foo();
temp.then((Future<int> future) {
future.then((int result) {
print(result);
});
});
}
Future<Future<int>> foo() {
return new Future<Future<int>>(() {
return new Future<int>(() => 5);
});
}
How to prevent unnecessary unwrapping?
In this case in async library 'Future' declared as generic class.
abstract class Future<T> {
}
If I create expression as the following
new Future<Future<int>>();
Then with type T specified as Future<int> which result expected from generic class Future?
I thing that result must be as specified in type argument T.
I.e. Future<int>.
But result is not as expected.
There is no information found about this abnormal behavior on Dart API site.
If this is a "feature" (but I think that abnormal behavior wrongly to call "feature') then why it not documented in Dart API?
How can be explained this discrepancy?
Why this code not generated errors and warnings?
Another IDENTICAL example but w/o using Future.
void main() {
var temp = foo();
temp.baz((Foo<int> foo) {
foo.baz((int result) {
print(result);
});
});
}
Foo<Foo<int>> foo() {
return new Foo<Foo<int>>(() {
return new Foo<int>(() => 5);
});
}
If in this case result will be as when using Future (i.e. unexpected) then how we can call this code?
Normal or abnormal?
Or maybe the Future in Dart some special (magic)?
Look at the api documentation
http://api.dartlang.org/docs/releases/latest/dart_async/Future.html
It says there:
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.
I guess that means you can't return a Future from a Future.
But you could return a list of futures.
void main() {
var temp = foo();
temp.then((List<Future<int>> list) {
list[0].then((int result) {
print(result);
});
});
}
Future<List<Future<int>>> foo() {
return new Future<List<Future<int>>>(() {
return [new Future<int>(() => 5)];
});
}
There is no need for any of that extra wrapping. According to the Future documentation:
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.
This means you can rewrite your code as:
import 'dart:async';
void main() {
var temp = foo();
temp.then((int result) {
print(result);
});
}
Future<int> foo() {
return new Future<int>(() {
return new Future<int>(() => 5);
});
}
This is a lot cleaner to work with and provides the expected result.

Resources