Reputation: 1052
I'm curerntly playing with Typescript
and ionic
and also new to async-await
on javascript. I'm trying to get a good undestanding of promises but I can't figure out how to wrap methods which call multiple promises to return a promise. I'll try to elaborate better:
Basically, I have an object which can create a SQLite
database, and when the create()
method is invoked, it would return a Promise
with the actual database object once it has been created.
Then, when the promise resolves and the DB object is returned, I need to use it to execute some statements in a transaction to create all the tables, and a new promise is returned when I invoke the execution of all the statements in the transaction.
Then when the transaction is finished and everything went good, I need to assign the database object to a class property and set a flag indicating database is created and ready to go.
So I thought it would be a good idea to wrap this database initialization stuff in a method called createDatabase()
or something like that, which returns a Promise<SQLiteObject>
, where SQLiteObject
represents the database. This method would be called on initialization and should return the SQLiteObject
representing the database once everything went OK, or throw an error which I would log in the .catch()
method of the Promise
.
I have a basic understanding of promises and how to use then()
and catch()
methods but I'm a bit confused when I have to create the database, then do something else when the promise resolves, and when everything is done, return a Promise
containing the DB object, which is an instance of the class SQLiteObject
.
CODE
Below is my current Typescript
code. It's not valid typescript as I don't know how to return the Promise<SQLiteObject>
from the async
function.
async createDatabase(): Promise<SQLiteObject> {
this.sqlite.create({
name: this.dbName,
location: this.dbLocation
}).then( (db: SQLiteObject) => {
// Insert all tables.
let createTableParam: string = `CREATE TABLE IF NOT EXISTS param (name PRIMARY KEY NOT NULL, value TEXT)`;
let createTableNews: string = `CREATE TABLE IF NOT EXISTS news (id PRIMARY KEY NOT NULL,title TEXT,
content TEXT, image TEXT, date DATE)`;
db.transaction(tx => {
tx.executeSql(createTableParam);
tx.executeSql(createTableNews);
// Add here more tables to create if needed
}
)
.then( () => {
console.log('Tables were created');
this.isActive = true;
})
.catch(error => {
console.log(`Error creating tables - ${error}`);
});
}).catch(
error => console.log(`Error at SQLite initialization - ${error}`)
);
}
RESEARCH SO FAR
Upvotes: 0
Views: 9460
Reputation: 519
It appears you're not resolving the promise.
A promise must be resolved or rejected so a async function is capable of responding with a value.
From TypeScript Deep Dive:
const promise = new Promise((resolve, reject) => {
resolve(123);
});
promise.then((res) => {
console.log('I get called:', res === 123); // I get called: true
});
promise.catch((err) => {
// This is never called
});
So in my opinion you should create a promise, and when the DB is created and everything resolve it, if there's a problem with the DB creation, reject it.
Remember you can chain promises, so you could chain them as you create your database.
From TypeScript Deep Dive:
The chain-ability of promises is the heart of the benefit that promises provide. Once you have a promise, from that point on, you use the then function to create a chain of promises.
Check this URL for more info about promises.
Upvotes: 2
Reputation: 95612
You used async
, so that means you can use await
inside the function any time you have a Promise
and write the code almost as though it were synchronous.
async createDatabase(): Promise<SQLiteObject> {
let db: SQLiteObject;
try {
db = await this.sqlite.create({
name: this.dbName,
location: this.dbLocation
});
} catch(error) {
console.log(`Error at SQLite initialization - ${error}`);
return;
);
// Insert all tables.
let createTableParam: string = `CREATE TABLE IF NOT EXISTS param (name PRIMARY KEY NOT NULL, value TEXT)`;
let createTableNews: string = `CREATE TABLE IF NOT EXISTS news (id PRIMARY KEY NOT NULL,title TEXT,
content TEXT, image TEXT, date DATE)`;
try {
await db.transaction(tx => {
tx.executeSql(createTableParam);
tx.executeSql(createTableNews);
// Add here more tables to create if needed
}
);
console.log('Tables were created');
this.isActive = true;
return db;
catch(error) {
console.log(`Error creating tables - ${error}`);
});
}
Without the await
you need to be sure to return that initial promise.
return this.sqlite.create({...
and then again further down you can return the db
object:
this.isActive = true;
return db;
Also you should avoid nesting the .then()
handlers: when you get another promise just return it from the first handler and chain another .then
on the end:
createDatabase(): Promise<SQLiteObject> {
let database: SQLiteObject = null;
return this.sqlite.create({
name: this.dbName,
location: this.dbLocation
})
.catch(error => console.log(`Error at SQLite initialization - ${error}`))
.then( (db: SQLiteObject) => {
// Insert all tables.
let createTableParam: string = `CREATE TABLE IF NOT EXISTS param (name PRIMARY KEY NOT NULL, value TEXT)`;
let createTableNews: string = `CREATE TABLE IF NOT EXISTS news (id PRIMARY KEY NOT NULL,title TEXT,
content TEXT, image TEXT, date DATE)`;
database = db;
return db.transaction(tx => {
tx.executeSql(createTableParam);
tx.executeSql(createTableNews);
// Add here more tables to create if needed
}
);
})
.then( () => {
console.log('Tables were created');
this.isActive = true;
return database;
})
.catch(error => console.log(`Error creating tables - ${error}`));
Upvotes: 2