Reputation: 385
Future readData() {
var completer = new Completer();
print("querying");
pool.query('select p.id, p.name, p.age, t.name, t.species '
'from people p '
'left join pets t on t.owner_id = p.id').then((result) {
print("got results");
for (var row in result) {
if (row[3] == null) {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, No Pets");
} else {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, Pet Name: ${row[3]}, Pet Species ${row[4]}");
}
}
completer.complete(null);
});
return completer.future;
}
The above is an example code taken from github SQLJocky Connector
I would like someone to explain me if possible why is the function which has a completer object created outside the pool.query is then calling a function completer.complete(null).
In short I am not able to understand the part after print executes.
Note:Kindly if possible I would also like to know how is future and Completer used for practical purpose both for DB and non DB operations.
I have explored the following links: Google groups discussion on Future and Completer
and the api reference documentation which is as given below Completer api reference and Future api Reference
Upvotes: 17
Views: 29320
Reputation: 71693
For the record, the example query code doesn't need to use a completer,. it can just continue from the future returned by query
.
Future readData() {
print("querying");
return pool.query('select p.id, p.name, p.age, t.name, t.species '
'from people p '
'left join pets t on t.owner_id = p.id').then((result) {
print("got results");
for (var row in result) {
if (row[3] == null) {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, No Pets");
} else {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, Pet Name: ${row[3]}, Pet Species ${row[4]}");
}
}
});
}
or using async
and await
:
Future readData() async {
print("querying");
var result = await pool.query(
'select p.id, p.name, p.age, t.name, t.species '
'from people p '
'left join pets t on t.owner_id = p.id');
print("got results");
for (var row in result) {
if (row[3] == null) {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, No Pets");
} else {
print("ID: ${row[0]}, Name: ${row[1]}, Age: ${row[2]}, Pet Name: ${row[3]}, Pet Species ${row[4]}");
}
}
}
Upvotes: 1
Reputation: 7393
The Future object that is returned by that method is, in a sense, connected to that completer object, which will complete at some point "in the future". The .complete() method is called on the Completer, which signals the future that it is complete. Here's a more simplified example:
import "dart:async";
Future<String> someFutureResult(){
final c = Completer<String>();
// `complete` will be called in 3 seconds by the timer.
Timer(const Duration(seconds: 3), () {
c.complete("you should see me second");
});
return c.future;
}
main(){
someFutureResult().then(print);
print("you should see me first");
}
Upvotes: 32
Reputation: 54377
Correct answer has errors in DartPad, the reason could be Dart version.
error : The argument type 'int' can't be assigned to the parameter type 'Duration'.
error : The argument type '(dynamic) → void' can't be assigned to the parameter type '() → void'.
The following snippet is complement
import 'dart:async';
Future<dynamic> someFutureResult(){
final c = new Completer();
// complete will be called in 3 seconds by the timer.
new Timer(Duration(seconds: 3), () {
print("Yeah, this line is printed after 3 seconds");
c.complete("you should see me final");
});
return c.future;
}
main(){
someFutureResult().then((dynamic result) => print('$result'));
print("you should see me first");
}
reslut
you should see me first
Yeah, this line is printed after 3 seconds
you should see me final
Upvotes: 6
Reputation: 143339
The Completer is used to provide a value to a future and signal it to fire any remaining callbacks and continuations that are attached to the future (i.e. at the call-site / in user code).
The completer.complete(null)
is what's used to signal to the future that the async operation has completed. The API for complete shows that it must supply 1 argument (i.e. not optional).
void complete(T value)
This code is not interested in returning a value, just notifying the call-site that the operation is complete. As it just prints, you will need to check the console for the output.
Upvotes: 4