1

我正在为 Ionic 应用程序使用离子原生 SQLite 数据库,并在使用 WebSQL 的浏览器中进行测试。在浏览器中一切正常,但在安卓设备中运行应用程序时。它给了我这样的错误Cannot read property 'transaction' of undefined。下面是代码供参考。

1) DBProvider.ts

import { Platform } from 'ionic-angular';
import { Injectable } from '@angular/core';
import { SQLite, SQLiteObject } from '@ionic-native/sqlite';

declare var window: any;
@Injectable()
export class DBProvider {
    DB_NAME: string = 'DailySheet.db';
    public websql = null;
    public sqlite: SQLite;
    sqliteobj: any;
    public AppUsers = [];

    constructor(public platform: Platform) {
        if (this.platform.is('core')) {
            this.websql = window.openDatabase(this.DB_NAME, "1.0", "Test DB", 2 * 1024 * 1024);
            console.log('Database opened.');
            this.createTable();
        }

        this.platform.ready().then(() => {
            if (!this.platform.is('core')) {
                this.sqlite.create({ name: this.DB_NAME, location: 'default' })
                    .then((db: SQLiteObject) => {
                        console.log('Database opened.');
                        this.sqliteobj = db;
                        this.createTable();
                    });
            }
        });
    }

    createTable() {
        this.query(`CREATE TABLE IF NOT EXISTS AppUser (
                         UserId INTEGER NOT NULL,
                         MobileNo   TEXT NOT NULL UNIQUE,
                         Email  TEXT,
                         PRIMARY KEY(UserId)
                     )`)
            .then(data => {
                console.log('Table created.');
            })
            .catch(err => {
                console.error('Unable to create initial storage tables', err.tx, err.err);
            });
    }

    getAppUsers(): Promise<any> {
        let query = 'SELECT * FROM AppUser';
        return this.query(query)
            .then(data => {
                if (data.res.rows.length > 0) {
                    console.log('Rows found.');
                    return data.res.rows;
                }
                else {
                    console.log('No rows found.');
                }
            });
    }

    insertAppUser(): Promise<any> {
        let id = 1;
        let mobileno = '8905606191';
        let email = 'niravparsana94@gmail.com';

        return this.query('INSERT INTO AppUser (UserId, MobileNo, Email) VALUES (' + id + ' ,\"' + mobileno + '\" ,\"' + email + '\")')
            .then(data => {
                console.log('Insert success.');
                return data;
            })
            .catch(err => {
                console.error('Unable to insert', err.tx, err.err);
            });
    }

    updateAppUser(UserId): Promise<any> {
        let query = "UPDATE Todo SET Email=? WHERE UserId=?";
        return this.query(query, ['niravparsana@outlook.com', UserId])
            .then(data => {
                console.log('AppUser Updated.');
                return data;
            })
            .catch(err => {
                console.error('Unable to update', err.tx, err.err);
            });
    }

    deleteAppUser(UserId): Promise<any> {
        let query = "DELETE FROM AppUser WHERE UserId=?";
        return this.query(query, [UserId])
            .then(data => {
                return data;
            })
            .catch(err => {
                console.error('Unable to delete', err.tx, err.err);
            });
    }

    query(query: string, params: any[] = []): Promise<any> {
        return new Promise((resolve, reject) => {
            try {
                if (this.platform.is('core')) {
                    this.websql.transaction((tx: any) => {
                        tx.executeSql(query, params,
                            (tx: any, res: any) => resolve({ tx: tx, res: res }),
                            (tx: any, err: any) => reject({ tx: tx, err: err }));
                    },
                        (err: any) => reject({ err: err }));
                }
                else {
                    this.sqliteobj.transaction((tx: any) => {
                        tx.executeSql(query, params,
                            (tx: any, res: any) => resolve({ tx: tx, res: res }),
                            (tx: any, err: any) => reject({ tx: tx, err: err }));
                    },
                        (err: any) => reject({ err: err }));
                }
            } catch (err) {
                reject({ err: err });
            }
        });
    }
}

2) home.ts

import { Component, OnInit } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { DBProvider } from '../../providers/DBProvider';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage implements OnInit {
  AppUsers: Array<Object>;

  constructor(public navCtrl: NavController, private platform: Platform, public db: DBProvider) {
  }

  ionViewDidLoad() {
    this.deleteAppUser();
    this.insertAppUser();
    this.getAllAppUsers();
  }

  ngOnInit() {
  }

  public deleteAppUser() {
    this.db.deleteAppUser(1)
      .then(data => {
        if (data.res.rowsAffected == 1) {
          console.log('AppUser Deleted.');
        }
        else {
          console.log('No AppUser Deleted.');
        }
      })
      .catch(ex => {
        console.log(ex);
      });
  }

  public insertAppUser() {
    this.db.insertAppUser()
      .then(data => {
      })
      .catch(ex => {
        console.log(ex);
      });
  }

  public getAllAppUsers() {
    this.db.getAppUsers()
      .then(data => {
        this.AppUsers = data;
      })
      .catch(ex => {
        console.log(ex);
      });
  }

}

在调试时,我发现代码在浏览器和移动设备中以不同的顺序运行。

在浏览器中

  1. DBProvider 构造函数
  2. this.CreateTable() 函数(DBProvider.ts)
  3. this.deleteAppUser() 函数(home.ts)
  4. this.insertAppUser() 函数(home.ts)
  5. this.getAllAppUsers() 函数(home.ts)

在安卓设备中

  1. DBProvider 构造函数
  2. this.deleteAppUser() 函数(home.ts)
  3. this.insertAppUser() 函数(home.ts)
  4. this.getAllAppUsers() 函数(home.ts)
  5. this.CreateTable() 函数(DBProvider.ts)

正如你可以在 DBProvider 构造函数中分配 this.sqliteobj 。但是在调试时我发现 home.ts 的函数在 this.sqliteobj 被分配之前调用,这就是为什么它会给出一个错误Cannot read property 'transaction' of undefined。但接下来的问题是为什么 home.ts 中的函数在 this.sqliteobj 被分配之前被调用?

4

1 回答 1

1

据我所知this.sqlite.create(...,每次调用 sqlite 数据库时都需要。因此,您必须在 sqliteobj 之前将其包含在查询函数中。

于 2017-05-25T15:49:36.797 回答