We are able to define an async inline method in different ways, Is there any difference in the result or under the hood?
1.
Future<void> counter() async => await Future<void>.delayed(
const Duration(seconds: 5),
() => print('Result'),
);
2.
Future<void> counter() async => Future<void>.delayed(
const Duration(seconds: 5),
() => print('Result'),
);
3.
Future<void> counter() => Future<void>.delayed(
const Duration(seconds: 5),
() => print('Result'),
);
Timing, if anything.
The async => await version waits for the delayed future created by Future.delayed to complete before returning, then it completes the returned future.
The async => version should do precisely the same, since the await is implicit in the return.
The => version returns the future created by Future.delayed directly.
In either case, the returned future will be completed after the 5 second duration has passed. It may or may not go through an extra intermediate microtask.
Related
when I run the below code snippet,I can't "Your order is: Large Latte".Instead I get "Your order is: Instance of '_Future".So what am I doing wrong?
Future<String> createOrderMessage() async{
var order = await fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
void main() {
print(createOrderMessage());
}
You have to await the first method call. So change to this:
void main() async {
print(await createOrderMessage());
}
If not, the main method will not wait for the Future to complete and instead just print that createOrderMessage() is an instance of a Future.
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.
I have a Map<String, Stream<dynamic>> and I want to convert it into a Stream<Map<String, dynamic>> which should yield the latest snapshot of values from the former. I need something like Rx.combineLatest( mapOfStreams.values, (list) => list ) but somehow keeping map keys.
I've found this solution, which seems to work (supposing keys and values of Map are always aligned), but I feel there must be something better:
final keys = mapOfStreams.keys.toList();
Rx.combineLatest( mapOfStreams.values, (list) => list.asMap().map( (i, value) => MapEntry(keys[i], value) ) );
This is my way
void main() async {
final streams = <String, Stream<dynamic>>{
'a': Stream<int>.periodic(const Duration(milliseconds: 200), (i) => i),
'b': Stream<int>.periodic(const Duration(milliseconds: 500), (i) => i),
'c': Stream<String>.value('Hello'),
};
final final$ = Rx.combineLatest(
streams.entries
.map((entry) => entry.value.map((v) => MapEntry(entry.key, v))),
(List<MapEntry<String, dynamic>> values) => Map.fromEntries(values),
);
final$.listen(print);
await Future.delayed(const Duration(seconds: 10));
}
In Flutter/Dart the examples sometimes show fat arrow and sometimes dont. Here are examples:
RaisedButton(
onPressed: () {
setState(() {
_myTxt = "Text Changed";
});
},
Elsewhere you see:
void main() => runApp(MyApp());
The fat arrow syntax is simply a short hand for returning an expression and is similar to (){ return expression; }.
According to the docs.
Note: Only an expression—not a statement—can appear between the arrow (=>) and the semicolon (;). For example, you can’t put an if statement there, but you can use a conditional expression
void main(){
final cls = TestClass();
cls.displayAnInt((){
//you can create statements here and then return a value
int num1 = 55;
int num2 = 1;
int sum = num1 + num2;
return sum;
});
cls.displayAnInt(() => 55 + 1); // simply return an int expression
}
class TestClass{
displayAnInt(makeIntFunc){
int intValue = makeIntFunc();
print('The int value is $intValue');
}
}
From the code above, You can see that multiline statement can be made when the callback function is used and then a value is returned, while the fat arrow simply has an expression with no return keyword.
Considering your answer about fat arrows not supporting multiline statements in dart. This is quite understandable since doing () => {somtheing} would imply you are returning a map and it would expect to see something like () => {'name':'John', 'age':25} and not () => { _myTxt = "Text Changed";_myTxt = "Never Mind"; } .
=> is used to return a value of an anonymous function.
() {} lets you execute multiple statements.
while
() => {myVar} or () => myVar; allows one single statement.
() => myVar; is short and simple when returning one statement.
The same logic goes for creating non anonymous functions too.
Single statement func
func() => y = x + x;
Multiple statement func
func () {
x = x + x;
print(x + ' value of x');
};
I found that the mean the exact same thing. The only difference is that you can use (you don't have to) the fat arrow if there is only one statement. Following is the above RaisedButton declaration with the fat arrow. Notice I had to remove two curly braces and one semi-colon:
RaisedButton(
onPressed: () {
setState(() =>
_myTxt = "Text Changed"
);
},
If you are used to other languages that allow you to put multiple statements after a fat arrow you'll you'll find that you can't in dart and if you try you'll get an error as in the following:
this wont work
RaisedButton(
onPressed: () {
setState(() => {
_myTxt = "Text Changed";
_myTxt = "Never Mind";
});
},
They are both for expressing anonymous functions. The fat arrow is for returning a single line, braces are for returning a code block.
A fat arrow trying to return a code block will not compile.
There seems to be one difference at least in case of Dart version 2.10:
If the expression to be executed is a Future, then the execution order is not the same.
=>
new Future(() => print('future #1 of 2'))
.then((_) => new Future(() => print('future #1a (a new future)')))
.then((_) => print('future #1b'));
new Future(() => print('future #2 of 2'))
.then((_) => new Future(() => print('future #2a (aa new futue)' )))
.then((_) => print('future #2b'));
The result is:
future #1 of 2
future #2 of 2
future #1a (a new future)
future #1b
future #2a (aa new futue)
future #2b`
{} :
new Future(() => print('future #1 of 2'))
.then((_) => new Future(() => print('future #1a (a new future)')))
.then((_) => print('future #1b'));
new Future(() => print('future #2 of 2'))
.then((_) { new Future(() => print('future #2a (aa new futue)' )); })
.then((_) => print('future #2b'));
The result is
future #1 of 2
future #2 of 2
future #2b
future #1a (a new future)
future #1b
future #2a (a new futue)
Fat Aarrow => Single line of code => Expression form, does not use return statement, the expression is automatically returned
void main() => runApp(MyApp()); // you cannot specify return here. This
is the turned value from the function. This is shorthand form
No fat arrow, uses {}, can have multiple statements, have to use return statement if we want to return a value, if not return can be skipped
setState(() {
_myTxt = "Text Changed";
});
I'm searching for the source of async/await implementations.
I would like to know how do they truly works in order to hack into future.then() to detect if there is code awaiting for execution or not.
Edit
This is what I'm willing to accomplish:
TrackingCompleter completer = new TrackingCompleter();
TrackingFuture future = completer.future;
print("isAwaited: ${future.isAwaited} (F)");
new Future.delayed(new Duration(milliseconds: 500), () {
future.then((_) {
print("executing sorping");
print("isThenExecuted: ${future.thenExecuted} (F)");
new Future.delayed(new Duration(milliseconds: 500), () {
print("isThenExecuted: ${future.thenExecuted} (T)");
exit(1);
});
});
print("isAwaited: ${future.isAwaited} (T)");
print("isThenExecuted: ${future.thenExecuted} (F)");
completer.complete();
});
As far, that's working. What I'd like to do now is to detect if future.then is called manually in the code or automatically with an await statement.
The async/await implementation is based on futures.
Basically, await creates a function that contains the rest of the current function (the "continuation" of the await expression), and then calls then on the future you await with that function as argument.
There are more details needed to handle errors, but that's basically it.
In your case, if you want to know if future.then is called, I recommend just wrapping that particular future. Example:
import "package:async/async.dart";
class ThenWrapper<T> extends DelegatingFuture<T> {
void Function(S Function(T), S Function(Object, StackTrace)) _callback;
ThenWrapper(Future<T> future, this._callback): super(future);
Future<S> then<S>(S onValue(T), {S onError(error, StackTrace st)}) {
_callback(onValue, onError);
return super.super(onValue, onError);
}
}
...
TrackingFuture future = new ThenWrapper(completer.future, ...);
You can change the callback to do whatever you want.