-1

我目前正在嘗試爲react-native項目實現react-native-sqlite-storage插件,該代碼基於的原始repo上位於react-native-sqlite-storage關閉不是iOS中的功能

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

我重寫位於在利用經由JS承諾插件庫的SRC文件夾的示例腳本。我重新創建的類幾乎完全可以工作,並且可以在iOS模擬器中執行。但是,使用close()函數關閉數據庫時出現錯誤 - 調試時返回的錯誤爲

that.db.close()不是函數。

引起錯誤的行是下面(apparantly)

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

爲類的完整代碼如下。任何幫助解決這個問題非常感謝。 (注意,我保留原作者的參考,現在使用'that'作爲'this',意圖將'''稍後'重構成'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); 

這裏是從iOS模擬器中運行的反應,本機應用程序的詳細的錯誤信息(我削除項目名稱):

enter image description here

回答

1

你必須承諾啓用前期。這意味着所有的數據庫操作都會返回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); 

我認爲這是不正確的,因爲這裏沒有返回分貝,不能分配給that.db

您可以嘗試分配數據庫裏面的that.db然後()處理程序 - onOpenDBSuccess。 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); 
      });