cgomes
March 31, 2017, 9:21pm
1
I’m trying to get informations from SQLite query:
data-provider.ts
import { Injectable } from '@angular/core';
import { SQLite, SQLiteObject } from '@ionic-native/sqlite';
@Injectable()
export class DatabaseProvider {
query: any;
constructor(public sqlite: SQLite) {
this.query = [];
this.sqlite.create({
name: 'data.db',
location: 'default'
}).then((db: SQLiteObject) => {
db.executeSql('CREATE TABLE IF NOT EXISTS tasks(id INTEGER PRIMARY KEY AUTOINCREMENT, description VARCHAR(50))', {})
.then(() => console.log('Executed create table'))
.catch(e => console.log(e.message));
}).catch(e => console.log(e.message));
}
selectAll() {
let tmp = [];
this.sqlite.create({
name: 'data.db',
location: 'default'
}).then((db: SQLiteObject) => {
db.executeSql('SELECT * FROM tasks', {})
.then(function(resultSet){
for(var x = 0; x < resultSet.rows.length; x++) {
tmp.push(resultSet.rows.item(x).description);
}
console.log('Executed select');
}).then(() => {
console.log('Returning');
return tmp;
}).catch(e => console.log(e.message));
}).catch(e => console.log(e.message));
}
}
home.ts
import { Component } from '@angular/core';
import { DatabaseProvider } from '../../providers/database-provider'
import { NavController, Platform } from 'ionic-angular';
@Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class HomePage {
tasks: any;
constructor(public navCtrl: NavController, public sqlProvider: DatabaseProvider, public platform: Platform) {
this.platform.ready().then(() => {
this.tasks = this.sqlProvider.selectAll();
console.log('Printing tasks: ' + this.tasks);
})
}
}
log
[18:16:20] console.log: OPEN database: data.db
[18:16:20] console.log: OPEN database: data.db - OK
[18:16:20] console.log: Ionic Native: deviceready event fired after 861 ms
[18:16:20] console.log: database already open: data.db
[18:16:20] console.log: Printing tasks: undefined
[18:16:20] console.log: Executed create table
[18:16:20] console.log: Executed select
[18:16:20] console.log: Returning
as you can see in log, ionic is printing before executing all the SQLite queries.
When selectAll()
returns is completely unrelated to when the stuff it is doing is completed. A good rule of thumb when dealing with asynchronous tasks is “make ‘return’ the very first word of all your functions”, and if you follow it here, you should be happy:
selectAll(): Promise<Task[]> {
return this.sqlite.create({}).then((db) => {
// do other db stuff
});
}
constructor() {
platform.ready().then(() => {
sqlProvider.selectAll().then((tasks) => {
// only in here can we rely on tasks
});
});
}
cgomes
April 1, 2017, 2:11pm
3
There’s must be something wrong, the log is still printing before executing SQLite query
obs: other typer other than void gives an error
selectAll(): Promise<void> {
return this.sqlite.create({
name: 'data.db',
location: 'default'
}).then((db: SQLiteObject) => {
db.executeSql('SELECT * FROM tasks', {})
.then(function(resultSet){
let tmp = [];
for(var x = 0; x < resultSet.rows.length; x++) {
tmp.push(resultSet.rows.item(x).description);
}
console.log('Executed select');
}).catch(e => console.log(e.message));
}).catch(e => console.log(e.message));
}
constructor(public navCtrl: NavController, public sqlProvider: DatabaseProvider, public platform: Platform) {
this.platform.ready().then(() => {
this.sqlProvider.selectAll().then((tasks) => {
this.lista = tasks;
console.log('tasks: ' + tasks);
});
})
}
log
[11:10:47] console.log: OPEN database: data.db
[11:10:47] console.log: OPEN database: data.db - OK
[11:10:47] console.log: Ionic Native: deviceready event fired after 820 ms
[11:10:47] console.log: database already open: data.db
[11:10:47] console.log: Executed create table
[11:10:47] console.log: tasks: undefined
[11:10:47] console.log: Executed select
You’re not returning tmp
out of the inner resolution.
1 Like
cgomes
April 1, 2017, 8:52pm
5
I did this and it worked
selectAll(): Promise<string[]> {
return new Promise<string[]>((resolve, reject) => {
let tmp = Array<string>();
this.sqlite.create({
name: 'data.db',
location: 'default'
}).then((db: SQLiteObject) => {
db.executeSql('SELECT * FROM tasks', {})
.then(function(resultSet){
for(var x = 0; x < resultSet.rows.length; x++) {
tmp.push(resultSet.rows.item(x).description);
}
console.log('Executed select');
resolve(tmp);
}).catch(e => console.log(e.message));
}).catch(e => console.log(e.message));
})
}
Thank you for your help
You shouldn’t need to be explicitly instantiating a promise. Just returning tmp
out if its should have been sufficient.
1 Like
cgomes
April 2, 2017, 12:05am
7
Returning tmp
was giving me these errors:
Type 'any[]' is not assignable to type 'Promise<string[]>'.
or
Type 'any[]' is not assignable to type 'Promise<any[]>'.
Dealing with actual SQLite is a pain, so I mocked this up, which will hopefully be similar enough that you can adapt it. It works as expected in a sample project:
makeDb(): Promise<any> {
let db:any = {};
db.executeSql = () => {
return Promise.resolve(["banana", "cherimoya"]);
};
return Promise.resolve(db);
}
loadEverything(): Promise<string[]> {
return this.makeDb().then((db) => {
return db.executeSql().then((results) => {
let rv = [] as string[];
for (let i = 0; i < results.length; ++i) {
rv.push(results[i]);
}
return rv;
});
})
}
onLoad(): void {
this.loadEverything().then((fruits) => {
this.fruits = fruits;
});
}
When I trigger onLoad()
from a button, this.fruits
is set to ['banana', 'cherimoya']
.