0

Am implemenmting chained promises but one function fails to be executed Basically i have the following functions which return promises

1. open database
2. add record // incase record exists remove it
3. remove record called from no 2

This is the way i have implemented

    openDb(): Promise<boolean> {   //opens database
    return new Promise((resolve, reject) => {
        this.sqlite.create({
            name: this.dbname,
            location: this.dblocation
        })
            .then((db: SQLiteObject) => {
                this.database = db;
                resolve(true)
            })
            .catch(e => reject(e.message));
    });
}

Then the add record

    add(item: string, value: any): Promise<boolean> {
    return new Promise((resolve, reject) => {
        this.openDb()
            .then(() => {
                this.database.transaction(
                    (tx: any) => {
                        tx.executeSql(`
                          CREATE TABLE IF NOT EXISTS '${tbl_name}'  
                                (item_id INTEGER PRIMARY KEY AUTOINCREMENT, item unique, value)` ); //incase tbl not there

                         this.remove(item) //next function which gets executed
                            .then(() => {

                                ///THIS PART IS NEVER EXECUTED
                                tx.executeSql(`
                                INSERT INTO '${tbl_name}' (item, value) VALUES(?, ?)`, [item, value],
                                    (t: any, results: any) => {
                                        console.log("executed successifully");
                                        resolve(true)
                                    },
                                    (t: any, message: any) => {
                                        console.log("Failed to execute");
                                        reject(false)

                                    })
                            })
                            .catch(reject(false))
                    }
                );

            })
            .catch(e => reject(e.essage));
    });
}

The the remove item function

    remove(item: string): Promise<boolean> {
    return new Promise((resolve, reject) => {
        this.openDb()
            .then(() => {
                this.database.transaction(
                    (tx: any) => {
                         tx.executeSql(`
                              DELETE FROM '${tbl_name}'  WHERE item ='${item}'
                              `, [],
                            (t: any, results: any) => {
                                console.log("executed successifully");
                                resolve(true)
                            },
                            (t: any, message: any) => {
                                console.log("Failed to execute");
                                reject(false)

                            })
                    }
                );

            })
            .catch(e => reject(e.essage));
    });
}

The remove item is executed successifully but the add block is never executed insted an error is thrown

InvalidStateError: DOM Exception 11: This transaction is already finalized.
 Transactions are committed after its success or failure handlers are called. 
 If you are using a Promise to handle callbacks, be aware that implementations
   following the A+ standard adhere to run-to-completion semantics
     and so Promise resolution occurs on a subsequent tick and therefore 
   after the transaction commits

What could be wrong?

Geoff
  • 6,277
  • 23
  • 87
  • 197
  • There are a few things that come to mind when I am reading your code. **1)** You commit the [explicit promise construction antipattern](https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it). In a promise-based API like the sqlite library you use, it is *never* necessary to construct new promises and there are good reasons not to do it. Remove every line that calls `new Promise()`, `reject()`, or `resolve()`. **2)** In a sound database design, it's not necessary to create dynamically named tables on the fly. Rework your DB. – Tomalak Jul 02 '17 at 07:18
  • **3)** When you use a promise-based API and still end up with code that looks like callback hell (like a sideways pyramid) then you are doing something wrong. Flatten out your code. (In this case, much of the unnecessary complexity goes away when you remove the superfluous promise creation. More goes away when you kill off the part that creates dynamically named tables.) – Tomalak Jul 02 '17 at 07:22
  • 1
    Final hint with regard to DB design: When you create many tables that have the same columns but different names, what you really want to do is create a single table with an additional "category" column. Don't let your application change the DB schema as a normal part of its operation, this is a recipe for disaster. – Tomalak Jul 02 '17 at 07:29

1 Answers1

0

The transaction is finished when you're trying to add into the table because of the callback in this.remove(item) will be executed asynchronously after this.database.transaction call is done.

shadeglare
  • 7,006
  • 7
  • 47
  • 59