Pass function as parameter in Dart - dart

Hello: I need pass a function (event handler) as parameter to other function site in other class:
classB
{
ClassB(){}
/***/
load (void onData(Event e))
{
ImageElement ie=new ImageElement();
ie.onLoad.listen( onData );
ie.src='hello.png';
}
/***/
}
classA
{
List<ClassB> lcb=new List();
ClassA(){}
/****/
void handler(Event e) {
/****/
}
myFunction() {
/***/
for (var i=0; i < lcb.length; i++)
{
***
lcb[i].load( handler );
***
}
/***/
}
}
It seems right in principle, but does not work. The function that is passed is never executed.
Anyone have any idea what is the correct way?

Looks good and should work especially after your recent update with listen.
Why do you expect the ImageElement to fire. You have to assign a src and attach it to the DOM to make it load and fire onload.

Related

try/catch block in calling generator function is never called

Can someone please explain to me why the calling generator function try/catch block is never run?
/// Dart program with nested stream for showing why try/catch blocs
/// in calling generator function is never called.
void main() async {
try {
await for (var val in generator()) {
print('Value: $val');
}
} catch (e) {
print(e.toString());
}
}
Stream<int> generator() async* {
for (int i = 0; i < 10; i++) {
try {
yield* generator2();
yield i;
} catch (e) {
// This catch block is never called. Never!
print('Woot');
}
}
}
Stream<int> generator2() async* {
for (int i = 100; i < 110; i++) {
if (i == 105) {
throw GeneratorException('Error on generating $i');
}
yield i;
}
}
class GeneratorException {
const GeneratorException(this.message);
final String message;
}
You can also try the below dartpad:
https://nullsafety.dartpad.dev/437b31a747cf7bacfa2332408c98f849
I think it is by design if you read the Dart specification:
If m is marked async*(9), then:
...
The o stream is listened to, creating a subscription s, and for each event x, or error e with stack trace t, of s:
...
Otherwise, x, or e with t, are added to the stream associated with m in the order they appear in o. Note that a dynamic error occurs if x is added and the dynamic type of x is not a subtype of the element type of said stream. The function m may suspend.
https://dart.dev/guides/language/specifications/DartLangSpec-v2.10.pdf
So when you do yield* you are forwarding all events from this Stream including errors.

What does void Function() do in Dart?

I´m quite new to dart and wondering what this "wrapped" function exactly does?
It´s called like a normal function with "connectUnits(userRepo)":
void Function(
Store<AppState> store,
dynamic action,
NextDispatcher next,
) connectUnits(
UnitsRepository unitsRepository,
) {
return (store, action, next) {
unitsRepository.units().listen((units) {
store.dispatch(LoadUnitsAction(units));
next(action);
});
};
}
Thanks & best,
Michael
Functions are first class citizens in Dart. Your example defines a function named connectUnits that returns a function with a signature void Function(Store<AppState> store, dynamic action, NextDispatcher next).
To better understand, your code is the same as:
// define a kind of function
typedef MyFunction = void Function(Store<AppState> store, dynamic action, NextDispatcher next);
MyFunction connectUnits(UnitsRepository unitsRepository) {
return (store, action, next) {
unitsRepository.units().listen((units) {
store.dispatch(LoadUnitsAction(units));
next(action);
});
};
}

Some explanations about completer

Hello everyone
I have one class 'Example' who needs to do some computation. I call start() which call _next(). During the computation _next() calls itself couple of time but in my example I simulate that with a Timer. here is my code
import "dart:async";
main() {
Example ex = new Example();
for (var i = 0 ; i < 3 ; i++) {
ex.start().then((nbr) {
print(nbr);
});
}
}
class Example {
/// for _next
Completer _insideCompleter;
/// from start() to outside
Completer _outsideCompleter;
Example();
/// start is just a better public api than next when we start the exercise
Future<int> start() {
_insideCompleter = new Completer();
_outsideCompleter = new Completer();
_next().then((int value) {
print("value: $value");
_outsideCompleter.complete(value);
}).catchError((message) {
print("information: $message");
});
return _outsideCompleter.future;
}
/// _next handle the flow with the status
Future<int> _next() {
new Timer(new Duration(seconds: 6), () {
_insideCompleter.complete(15);
});
return _insideCompleter.future;
}
}
it finishes with : Bad state: Future already completed. but as you can see in the start(). the Completer are re-created with new. So I don't understand why it is already complete.
If anybody can explain why it's not correct to code like that and maybe give me some interesting links it would be great
Cheers!
I'm not entirely sure what your intention with the code is but I think you should either
Example ex = new Example();
for (var i = 0 ; i < 3 ; i++) { // create a new Example() for each iteration here
ex.start().then((nbr) { // or ensure that the next iteration is not executed
print(nbr); // before the previous is completed.
});
}
with this code ex.start() is called 3 times before the first call is completed.
Here the main issue is about completers called in the callback function
_next().then((int value) {
print("value: $value");
_outsideCompleter.complete(value); // this line
})
and
new Timer(new Duration(seconds: 6), () {
_insideCompleter.complete(15); // this line
});
Because this 2 function are called after your loop and your completer are attribute, all the callback will use the latest _outsideCompleter and _insideCompleter created.
So after than one of the callback have "consume" your completer, the others will create exception of 'Bad state: Future already completed'
here a version that works
import "dart:async";
main() {
Example ex = new Example();
for (var i = 0 ; i < 3 ; i++) {
ex.start().then((nbr) {
print(nbr);
});
}
}
class Example {
Example();
/// start is just a better public api than next when we start the exercise
Future<int> start() {
var outsideCompleter = new Completer(); // create localy each times
_next().then((int value) {
print("value: $value");
outsideCompleter.complete(value);
}).catchError((message) {
print("information: $message");
});
return outsideCompleter.future;
}
/// _next handle the flow with the status
Future<int> _next() {
var insideCompleter = new Completer(); // create localy each times
new Timer(new Duration(seconds: 6), () {
insideCompleter.complete(15);
});
return insideCompleter.future;
}
}

Implementing onData in 'dart:html' dispatchEvent

I am developing an application but I noticed that each class has a lot of similar code to the one below addRace method in the class below:
#CustomTag( 'race-view' )
class RaceViewForm extends PolymerElement
{
RaceViewForm.created() : super.created();
void addRace( Event e, var detail, Element target )
{
var raceElem = $['race'];
if( raceElem.children.length < 1 )
{
raceElem.children.add( new Element.tag( 'race-form' ) );
}
raceElem.on[ DELETE_BUTTON_FORM_EVENT ]
.listen( (Event e)
{
(e.target as Element).remove();
dispatchEvent( new CustomEvent( RACE_VIEW_EVENT, detail:new Race() ));
});
}
}
I have attempted to move the repeating code into a library called shared.dart with the following refactoring:
import 'dart:html';
import 'package:observe/observe.dart';
...
void addForm( Element target, String eventName, String dispatchEventName, dynamic instance )
{
var element = target;
if( element.children.length < 1 )
{
element.children.add( new Element.tag( 'race-form' ) );
}
element.on[ eventName ]
.listen( (Event e)
{
(e.target as Element).remove();
dispatchEvent( new CustomEvent( dispatchEventName, detail:instance ));
});
}
However, the dart IDE flags the dispatchEvent method in the addForm method as being not defined with parameter onData (dynamic) -> void. Given that dispatchEvent is in the 'dart:html' package, I am uncertain as to what to do next.
I didn't find a dispatchEvent() in dart:html (top level) only as method of the Node class. You need to pass your Polymer element instance to the library method.
You could implement it as a mixin to make it easier to reuse.
See https://github.com/donny-dont/Pixelate/blob/master/lib/components/expander/expander.dart#L41 (Expandable, Customizeable) for an example.

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