Reputation: 1191
I get my articles from my JSON API in asynchronous and I would like to do a local storage with SQLite when the user does not have an internet connection, but I have these two errors :
cordova_not_available
ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'executeSql' of undefined TypeError: Cannot read property 'executeSql' of undefined at SqliteService.webpackJsonp.173.SqliteService.createTables (Sqlite.service.ts:30) at SqliteService.webpackJsonp.173.SqliteService.saveAllArticles (Sqlite.service.ts:114) at new AlaUnePage
I created a service sqlite.service.ts, it is supposed to create my database, my tables and insert each article when I call in the constructor of my AlaUnePage.
The code of my service :
import {Injectable} from '@angular/core';
import {SQLite, SQLiteObject} from '@ionic-native/sqlite';
import {ArticlesService} from "./articles.service";
const DATABASE_FILE_NAME: string = "data.db";
@Injectable()
export class SqliteService {
private db: SQLiteObject;
constructor(protected sqlite: SQLite, protected articlesService: ArticlesService) {
}
public createDatabaseFile() {
this.sqlite.create({
name: DATABASE_FILE_NAME,
location: 'default'
})
.then((db: SQLiteObject) => {
this.db = db;
this.createTables();
console.log("Database créée");
})
.catch(e => console.log("Erreur : "+e));
}
public createTables() {
console.log('ici');
this.db.executeSql(
'CREATE TABLE IF NOT EXISTS all_articles(' +
'id INT PRIMARY KEY, ' +
'titre TEXT, ' +
'introduction TEXT, ' +
'image TEXT, ' +
'redacteur_nom TEXT, ' +
'redacteur_twitter TEXT, ' +
'date_publication NUMERIC, ' +
'contenu_part1 TEXT, ' +
'tweet TEXT,' +
'image2 TEXT, ' +
'contenu_part2 TEXT, ' +
'tweet2 TEXT, ' +
'image3 TEXT, ' +
'contenu_part3 TEXT, ' +
'tweet3 TEXT, ' +
'image4 TEXT, ' +
'contenu_part4 TEXT, ' +
'tweet4 TEXT, ' +
'image5 TEXT, ' +
'contenu_part5 TEXT, ' +
'tweet5 TEXT, ' +
'image6 TEXT, ' +
'contenu_part6 TEXT, ' +
'tweet6 TEXT, ' +
'image7 TEXT, ' +
'contenu_part7 TEXT, ' +
'tweet7 TEXT, ' +
'image8 TEXT, ' +
'contenu_part8 TEXT, ' +
'tweet8 TEXT, ' +
'image9 TEXT, ' +
'contenu_part9 TEXT, ' +
'tweet9 TEXT, ' +
'image10 TEXT, ' +
'contenu_part10 TEXT, ' +
'tweet10 TEXT)', {})
.then(() => {
this.db.executeSql(
'CREATE TABLE IF NOT EXISTS all_articles(' +
'id INT PRIMARY KEY, ' +
'titre TEXT, ' +
'introduction TEXT, ' +
'image TEXT, ' +
'redacteur_nom TEXT, ' +
'redacteur_twitter TEXT, ' +
'date_publication NUMERIC, ' +
'contenu_part1 TEXT, ' +
'tweet TEXT,' +
'image2 TEXT, ' +
'contenu_part2 TEXT, ' +
'tweet2 TEXT, ' +
'image3 TEXT, ' +
'contenu_part3 TEXT, ' +
'tweet3 TEXT, ' +
'image4 TEXT, ' +
'contenu_part4 TEXT, ' +
'tweet4 TEXT, ' +
'image5 TEXT, ' +
'contenu_part5 TEXT, ' +
'tweet5 TEXT, ' +
'image6 TEXT, ' +
'contenu_part6 TEXT, ' +
'tweet6 TEXT, ' +
'image7 TEXT, ' +
'contenu_part7 TEXT, ' +
'tweet7 TEXT, ' +
'image8 TEXT, ' +
'contenu_part8 TEXT, ' +
'tweet8 TEXT, ' +
'image9 TEXT, ' +
'contenu_part9 TEXT, ' +
'tweet9 TEXT, ' +
'image10 TEXT, ' +
'contenu_part10 TEXT, ' +
'tweet10 TEXT)', {})
.then(() => console.log('Executed SQL'))
.catch(e => console.log(e));
}).catch(e => console.log(e));
}
public saveAllArticles(allArticles)
{
this.createTables();
allArticles.subscribe(article => {
console.log(article['article_id']);
this.db.executeSql('INSERT INTO all_articles (' +
'id,' +
'titre,' +
'introduction,' +
'image,' +
'redacteur_nom,' +
'redacteur_twitter,' +
'date_publication,' +
'contenu_part1,' +
'tweet,' +
'image2,' +
'contenu_part2,' +
'tweet2,' +
'image3,' +
'contenu_part3,' +
'tweet3,' +
'image4,' +
'contenu_part4,' +
'tweet4,' +
'image5,' +
'contenu_part5,' +
'tweet5,' +
'image6,' +
'contenu_part6,' +
'tweet6,' +
'image7,' +
'contenu_part7,' +
'tweet7,' +
'image8,' +
'contenu_part8,' +
'tweet8,' +
'image9,' +
'contenu_part9,' +
'tweet9,' +
'image10,' +
'contenu_part10,' +
'tweet10) VALUES ('
+article.article_id+ ','
+article.article_titre+ ',' +
+article.article_introduction+ ',' +
+article.article_image+ ',' +
+article.article_redacteur_nom+ ',' +
+article.article_redacteur_twitter+ ',' +
+article.article_date_publication+ ',' +
+article.article_contenu_part1+ ',' +
+article.article_tweet+ ',' +
+article.article_image2+ ',' +
+article.article_contenu_part2+ ',' +
+article.article_tweet2+ ',' +
+article.article_image3+ ',' +
+article.article_contenu_part3+ ',' +
+article.article_tweet3+ ',' +
+article.article_image4+ ',' +
+article.article_contenu_part4+ ',' +
+article.article_tweet4+ ',' +
+article.article_image5+ ',' +
+article.article_contenu_part5+ ',' +
+article.article_tweet5+ ',' +
+article.article_image6+ ',' +
+article.article_contenu_part6+ ',' +
+article.article_tweet6+ ',' +
+article.article_image7+ ',' +
+article.article_contenu_part7+ ',' +
+article.article_tweet7+ ',' +
+article.article_image8+ ',' +
+article.article_contenu_part8+ ',' +
+article.article_tweet8+ ',' +
+article.article_image9+ ',' +
+article.article_contenu_part9+ ',' +
+article.article_tweet9+ ',' +
+article.article_image10+ ',' +
+article.article_contenu_part10+ ',' +
+article.article_tweet10+
')', {})
.then(() => {
this.db.executeSql('', {})
.then(() => console.log('Executed SQL'))
.catch(e => console.log(e));
}).catch(e => console.log(e));
});
}
}
The constructor in my page :
constructor(public navCtrl: NavController,
public modalCtrl: ModalController,
protected articlesService: ArticlesService,
protected sqliteService: SqliteService,
private network: Network,
public toastCtrl: ToastController)
{
this.observable$ = this.articlesService.getAllArticles();
sqliteService.createDatabaseFile();
this.sqliteService.saveAllArticles(this.observable$);
}
After your suggestions :
Can you help me please ?
Thanks in advance
Upvotes: 0
Views: 2027
Reputation: 7326
There are an async issue in this code:
sqliteService.createDatabaseFile();
this.sqliteService.saveAllArticles(this.observable$);
saveAllArticles
may be called before createDatabaseFile
so why you get an undefined db
Solution is to return a promise (because sqlite already use promise) in your methods in the service, for example:
public createDatabaseFile(): Promise<SQLiteObject> {
let promise = this.sqlite.create({
name: DATABASE_FILE_NAME,
location: 'default'
});
promise.then((db: SQLiteObject) => {
this.db = db;
this.createTables();
console.log("Database créée");
}).catch(e => console.log("Erreur : "+e));
return promise;
}
public createTables(): Promise<void> {
return this.db.executeSql(
'CREATE TABLE IF NOT EXISTS all_articles...'
).then(()=> {
return this.db.executeSql('CREATE TABLE IF NOT EXISTS all_articles ...')
});
}
Now they are all returning a promise and you can use like:
this.observable$ = this.articlesService.getAllArticles();
sqliteService.createDatabaseFile().then( (db) => {
this.sqliteService.createTables().then( () => {
this.sqliteService.saveAllArticles(this.observable$);
})
});
if you want to change saveAllArticles to use promise too:
public saveAllArticles(allArticles)
{
// you need to import toPromise()
// import 'rxjs/add/operator/toPromise';
return allArticles.toPromise().then(article => {
return this.db.executeSql('INSERT INTO all_articles (...)')
}).then(()=> {
return this.db.executeSql('', {})
})
}
Upvotes: 1