首页 文章

react-native-sqlite-storage close在iOS中不是一个函数

提问于
浏览
-1

我目前正在尝试为react-native项目实现 react-native-sqlite-storage 插件,此代码所依据的原始repo位于

https://github.com/andpor/react-native-sqlite-storage [2]

我重写了位于存储库的src文件夹中的示例脚本,该文件夹通过JS Promises使用该插件 . 我重新创建的类几乎完全正常工作,可以在iOS模拟器中执行 . 但是,使用close()函数关闭数据库时出错 - 调试时返回错误

that.db.close()不是函数 .

导致错误的行低于(显着)

that.db.close().then(onDbCloseSuccess).catch(onDbCloseError);

该类的完整代码如下所示 . 我们非常感谢您解决此问题的任何帮助 . (注意,我保留原作者暂时使用'that'作为'this'的意思,并打算将'that'重构为'this' .

'use strict';

import React, { Component } from 'react';
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    ListView
} from 'react-native';


import SQLite from 'react-native-sqlite-storage';
SQLite.DEBUG(true);
SQLite.enablePromise(true);

export default class ExampleClass extends Component {

    database_name = "Test.db";
    database_version = "1.0";
    database_displayname = "SQLite Test Database";
    database_size = 200000;
    db: Promise;
    state = { progress:[] };

  constructor(){
    super();
  }

  getInitialState(){
    return {
        progress: [],
        dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => any = (row1, row2) => { return row1 !== row2 ; },
        })
    };
  }

  componentWillUnmount(){
        this.closeDatabase();
  }

  setAppState(msg: string){
      this.state.progress.push(msg);
      this.setState(this.state);
  }

  errorCB(err) {
    console.log("(errorCB) ERROR: ", err);
    this.setAppState("ERROR: " + (err.message || err));
  }

  closeDatabase(){
        let that = this;
        if (that.db) {
            console.log("CLOSING DATABASE");
            that.setAppState("CLOSING DATABASE");

            const onDbCloseSuccess: (status: any) => void = (status: any) => {
                console.log("DATABASE CLOSED");
                that.setAppState("DATABASE CLOSED");
            };

            const onDbCloseError: (error: string) => void = (error: string) => {
                that.errorCB(error);
            };

            // error closing database? no close method()?
            that.db.close().then(onDbCloseSuccess).catch(onDbCloseError);

        } else {
            that.setAppState("DATABASE WAS NOT OPENED");
        }
  }

  deleteDatabase(){
    let that = this;

    that.setAppState("DELETING DATABASE");

    const onDeleteDBSuccess: () => void = () => {
        console.log("DATABASE DELETED");
        that.setAppState("DATABASE DELETED");
    };

    const onDeleteDBError: (error: string) => void = (error: string) => {
        console.log("ERROR DELETING DATABASE");
        that.errorCB(error);
    };

    SQLite.deleteDatabase(that.database_name).then(onDeleteDBSuccess).catch(onDeleteDBError);

  }

  queryEmployees(tx) {
        let that = this;
        console.log("Executing employee query");
        const q: string = `SELECT a.name, b.name as deptName FROM Employees a, Departments b WHERE a.department = b.department_id`;

        const executeSqlSuccess: Function = ([tx,results]) => {

            that.state.progress.push("QUERY COMPLETED");
            that.setState(that.state);

            const numRows: number = results.rows.length;
            for (let i = 0; i < numRows; i++) {
                let row = results.rows.item(i);
                that.state.progress.push(`Empl Name: ${row.name}, Dept Name: ${row.deptName}`);
            }
            that.setState(that.state);
        };

        const executeSqlFailure: (error: string) => void = (error: string) => {
            console.log(error);
        };

        tx.executeSql(q).then(executeSqlSuccess).catch(executeSqlFailure);
    }

    populateDB(tx) {
      console.log(`populateDB`);

        let that = this;
        that.setAppState("EXECUTING DROP STATEMENTS");

        tx.executeSql('DROP TABLE IF EXISTS Employees;');
        tx.executeSql('DROP TABLE IF EXISTS Offices;');
        tx.executeSql('DROP TABLE IF EXISTS Departments;');

        that.setAppState("EXECUTING CREATE STATEMENTS");

        const onCreateTableError: (error: string) => void = (error) => {
            that.errorCB(error);
        };

        tx.executeSql('CREATE TABLE IF NOT EXISTS Version( '
            + 'version_id INTEGER PRIMARY KEY NOT NULL); ').catch(onCreateTableError);

        tx.executeSql('CREATE TABLE IF NOT EXISTS Departments( '
            + 'department_id INTEGER PRIMARY KEY NOT NULL, '
            + 'name VARCHAR(30) ); ').catch(onCreateTableError);

        tx.executeSql('CREATE TABLE IF NOT EXISTS Offices( '
            + 'office_id INTEGER PRIMARY KEY NOT NULL, '
            + 'name VARCHAR(20), '
            + 'longtitude FLOAT, '
            + 'latitude FLOAT ) ; ').catch(onCreateTableError);

        tx.executeSql('CREATE TABLE IF NOT EXISTS Employees( '
            + 'employee_id INTEGER PRIMARY KEY NOT NULL, '
            + 'name VARCHAR(55), '
            + 'office INTEGER, '
            + 'department INTEGER, '
            + 'FOREIGN KEY ( office ) REFERENCES Offices ( office_id ) '
            + 'FOREIGN KEY ( department ) REFERENCES Departments ( department_id ));').catch(onCreateTableError);

        that.setAppState("EXECUTING INSERT STATEMENTS");

        tx.executeSql('INSERT INTO Departments (name) VALUES ("Client Services");');
        tx.executeSql('INSERT INTO Departments (name) VALUES ("Investor Services");');
        tx.executeSql('INSERT INTO Departments (name) VALUES ("Shipping");');
        tx.executeSql('INSERT INTO Departments (name) VALUES ("Direct Sales");');

        tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Denver", 59.8,  34.1);');
        tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Warsaw", 15.7, 54.1);');
        tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Berlin", 35.3, 12.1);');
        tx.executeSql('INSERT INTO Offices (name, longtitude, latitude) VALUES ("Paris", 10.7, 14.1);');

        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Sylvester Stallone", 2,  4);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Elvis Presley", 2, 4);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Leslie Nelson", 3,  4);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Fidel Castro", 3, 3);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Bill Clinton", 1, 3);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Margaret Thatcher", 1, 3);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Donald Trump", 1, 3);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Dr DRE", 2, 2);');
        tx.executeSql('INSERT INTO Employees (name, office, department) VALUES ("Samantha Fox", 2, 1);');

        console.log("ALL CONFIG SQL DONE");
    }

  populateDatabase(dbResult){
    let that = this;

    that.state.progress.push("Database integrity check");
    that.setState(that.state);

    const q: string = 'SELECT 1 FROM Version LIMIT 1';
    const executeSqlSuccess: () => void = () =>{
        that.state.progress.push("Database is ready ... executing query ...");
        that.setState(that.state);

        const transactionSuccess: () => void = () => {
            that.state.progress.push("Processing completed");
            that.setState(that.state);
        };

        const transactionFailure: (error: string) => void = (error: string) => {
            console.log(`*** transactionFailure error. details ***`, error);
        };

        dbResult.transaction(that.queryEmployees.bind(that)).then(transactionSuccess).catch(transactionFailure);
    };

    const executeSqlFailure: (error: string) => void = (error: string) =>{
        console.log("Received error: ", error);
        that.state.progress.push("DATABASE NOT READY ... POPULATING DATA");
        that.setState(that.state);

        const onPopulateDBSuccess: () => void = () =>{
            that.state.progress.push("Database populated ... executing query ...");
            that.setState(that.state);

            const onTransactionComplete = (result) => {
                console.log("Transaction is now finished");
                that.state.progress.push("Processing completed");
                that.setState(that.state);
                that.closeDatabase()
            };

            const onTransactionFailure: (error: string) => void = (error: string) => {
                console.log(`*** populateDatabase: transactionFailure error *** \n`,error);
            };


            dbResult.transaction(that.queryEmployees.bind(that)).then(onTransactionComplete).catch(onTransactionFailure);
        };

        const onPopulateDBFailure: Function = (error: string) => {
            console.log(error);
        };

        dbResult.transaction(that.populateDB.bind(that)).then(onPopulateDBSuccess).catch(onPopulateDBFailure);
    };

    dbResult.executeSql(q).then(executeSqlSuccess).catch(executeSqlFailure);
  }

  loadAndQueryDB(){
      const that = this;
      that.setAppState("PLUGIN INTEGRITY CHECK");

      const onOpenDBSuccess: (dbResult: any) => any = (dbResult: any) => {
          console.log('*** onOpenDBSuccess ***');
          console.log('DATABASE OPENED');
          that.state.progress.push('DATABASE OPENED');
          that.setState(that.state);
          console.log(dbResult);

          that.populateDatabase(dbResult);
      };

      const onOpenDBFailure: (error: string ) => void = (error: string) => {
          console.log('*** onOpenDBFailure ***');
          console.log(error);
      };

      const onEchoTestComplete: () => void = () => {
          console.log('*** onEchoTestComplete ***');
          that.state.progress.push("Integrity check passed ...");
          that.setState(that.state);

          that.state.progress.push("Opening database ...");
          that.setState(that.state);

          // create a database
          that.db = SQLite.openDatabase(this.database_name, this.database_version, this.database_displayname, this.database_size).then(onOpenDBSuccess).catch(onOpenDBFailure);
      };

      const onEchoTestFailure: () => void = () => {
          console.log('*** onEchoTestFailure ***');
          that.state.progress.push("echoTest failed - plugin not functional");
          that.setState(that.state);
      };

      SQLite.echoTest().then(onEchoTestComplete).catch(onEchoTestFailure);
  }

  runDemo(){
      this.state.progress = ["Starting SQLite Promise Demo"];
      this.setState(this.state);
      this.loadAndQueryDB();
  }

  render(){
      let ds = new ListView.DataSource({rowHasChanged: (row1, row2) => { return row1 !== row2;}});
      return (<View style={styles.mainContainer}>
        <View style={styles.toolbar}>
          <Text style={styles.toolbarButton} onPress={this.runDemo.bind(this)}>
            Run Demo
          </Text>
          <Text style={styles.toolbarButton} onPress={this.closeDatabase.bind(this)}>
            Close DB
          </Text>
          <Text style={styles.toolbarButton} onPress={this.deleteDatabase.bind(this)}>
            Delete DB
          </Text>
        </View>
        <ListView
            enableEmptySections={true}
            dataSource={ds.cloneWithRows(this.state.progress)}
            renderRow={this.renderProgressEntry}
            style={listStyles.liContainer}/>
      </View>);
  }

  renderProgressEntry(entry){
    return (<View style={listStyles.li}>
        <View>
            <Text style={listStyles.liText}>{entry}</Text>
        </View>
    </View>)
  }

}

const listStyles = StyleSheet.create({
    li: {
        borderBottomColor: '#c8c7cc',
        borderBottomWidth: 0.5,
        paddingTop: 15,
        paddingRight: 15,
        paddingBottom: 15,
    },
    liContainer: {
        backgroundColor: '#fff',
        flex: 1,
        paddingLeft: 15,
    },
    liIndent: {
        flex: 1,
    },
    liText: {
        color: '#333',
        fontSize: 17,
        fontWeight: '400',
        marginBottom: -3.5,
        marginTop: -3.5,
    },
});

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
    toolbar: {
        backgroundColor: '#51c04d',
        paddingTop: 30,
        paddingBottom: 10,
        flexDirection: 'row'
    },
    toolbarButton: {
        color: 'blue',
        textAlign: 'center',
        flex: 1
    },
    mainContainer: {
        flex: 1
    }
});

AppRegistry.registerComponent('ExampleClass', () => ExampleClass);

以下是运行react-native应用程序的iOS模拟器的详细错误消息(我清空了项目名称):

enter image description here

1 回答

  • 1

    您已预先启用了Promise . 这意味着所有数据库操作都将返回promise . openDatabase也以同样的方式工作 .

    你的代码是:

    // create a database
    that.db = SQLite.openDatabase(this.database_name, this.database_version, this.database_displayname, this.database_size).then(onOpenDBSuccess).catch(onOpenDBFailure);
    

    我认为这是不正确的,因为这里没有返回db,也无法分配给该.db

    您可以尝试在then()处理程序 - onOpenDBSuccess中将db分配给that.db . onOpenDBSuccess应该将db作为参数...

    SQLite.openDatabase({name : "test6.db"}).then((DB) => {
                    that.db = DB;
                    that.state.progress.push("Database OPEN");
                    that.setState(that.state);
                    that.populateDatabase(DB);
                }).catch((error) => {
                    console.log(error);
                });
    

相关问题