IBRIT
IBRIT

Reputation: 385

Completer and Future in dart?

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

Answers (4)

lrn
lrn

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

John Evans
John Evans

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

chunhunghan
chunhunghan

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

mythz
mythz

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

Related Questions