Search code examples
dartdart-async

sqljocky query does not have a method 'then' (dart database access)


I'm trying to code sql access to a database using sqljocky in Dart. As I want to make some computation with the result returned by my database Handler, the method return a Future.

But when I try to run it, I'm getting the following error:

Uncaught Error: The null object does not have a method 'then'`

I've ran the debugger and found that this error raise on:

db.query('select * from user where email="$email"').then(...)

but the catchError clause doesn't fire.

My handler method is:

// db is a ConnectionPool
Future<Map<String,String>> queryUser(String email){
    print(email);
    db.query('select * from user where email="${email}"').then((result) { // here raise the error
        Map<String,String> results = new Map<String,String>();
        result.forEach((row){
           results['status'] = '200'; 
           results['ID'] = row[0];
           results['Image'] = row[1];
           results['Name'] = row[2];
           results['Email'] = row[3];
           results['Password'] = row[4];
        });
        return results;
    }).catchError((error){
        Map<String,String> results = new Map<String,String>();
        results['status'] = '500';
        return results;
    });
}

And the method that call this handler is:

List getUser(String email) {
    Future<Map<String,String>> result = dbhandler.queryUser(email);
    result.then((Map<String,String> result) {
    String statuscode = result['status'];
    result.remove('status');
    String json = JSON.encode(result);
    List pair = new List();
    pair.add(statuscode);
    pair.add(json);
    return pair;
});

If I run the query directly in phpmyadmin, it return correct data, so it is correct.

Can someone give me a hint about how to solve it?


Solution

  • The queryUser() method will always return null, as there is no return statement. In the next release of Dart there will be a static hint warning for this, but at the moment there is none.

    Perhaps the code below is what you meant to do. Note the initial return statement before db.query(), and the extra result.toList() call. I haven't tested this, so there's probably a typo or two.

    Future<Map<String,String>> queryUser(String email){
        print(email);
        return db.query('select * from user where email="${email}"')
          .then((result) => result.toList())
          .then((rows) {
            var row = rows.single;
            Map<String,String> results = new Map<String,String>();
            results['status'] = '200'; 
            results['ID'] = row[0];
            results['Image'] = row[1];
            results['Name'] = row[2];
            results['Email'] = row[3];
            results['Password'] = row[4];
            return results;
          }).catchError((error){
            Map<String,String> results = new Map<String,String>();
            results['status'] = '500';
            return results;
          });
    }
    

    You can also make this a bit cuter using map literals:

    Future<Map<String,String>> queryUser(String email){
        return db.query('select * from user where email="${email}"')
          .then((result) => result.toList())
          .then((rows) => <String, String> {
            'status': '200',
            'ID': rows.single[0],
            'Image': rows.single[1],
            'Name': rows.single[2],
            'Email': rows.single[3],
            'Password': rows.single[4] })
          .catchError((error) => <String, String> {'status': '500'});
    }