javascript Cordova SQLite:无法读取 null 的属性“交易”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28464389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 09:01:23  来源:igfitidea点击:

Cordova SQLite: Cannot read property 'transaction' of null

javascriptandroidsqlitecordovaionic-framework

提问by Odyss3us

I am trying to integrate SQLite into my Ionic app, but I keep getting Cannot read property 'transaction' of nullwhile remote debugging or testing via the browser, when trying to query the DB for data on the device.

我正在尝试将 SQLite 集成到我的 Ionic 应用程序中,但是当我Cannot read property 'transaction' of null尝试在设备上查询数据库中的数据时,我一直在通过浏览器进行远程调试或测试。

So I have split up all of my configs, controllers and factories into separate files, all grouped by feature / module, so I inject each module's config file into the main app, and then inside of the config file I inject the controller and factory.

因此,我将所有配置、控制器和工厂拆分为单独的文件,全部按功能/模块分组,因此我将每个模块的配置文件注入主应用程序,然后在配置文件中注入控制器和工厂。

I am not sure if the way that I've structured the app might be breaking something?

我不确定我构建应用程序的方式是否会破坏某些内容?

Below I've listed all of the relevant files involved,

下面我列出了所有涉及的相关文件,

app.js

应用程序.js

var app = angular.module('app', ['ionic', 'ngCordova', 'app.config', 'login.config']);

app.run(['$rootScope', '$ionicPlatform', 'DB', function($rootScope, $ionicPlatform, DB) {

    $ionicPlatform.ready(function() {

        if (window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }

        if (window.StatusBar) {
            StatusBar.styleDefault();
        }

        if(navigator.splashscreen) {
            navigator.splashscreen.hide();
        }

        DB.init();

    });

}]);

app.config.js

应用配置文件

var app = angular.module('app.config', ['app.controller', 'app.factory']);

app.config(function($stateProvider, $urlRouterProvider, $httpProvider) {

    $stateProvider
        .state('app', {
            url: "/app",
            abstract: true,
            templateUrl: "templates/menu.html",
            controller: 'appController'
        });

    $urlRouterProvider.otherwise('/login');

});

app.constant('DB_CONFIG', {
    name: 'database.db',
    tables: [
        {
            name: 'users',
            columns: [
                {name: 'id', type: 'integer primary key'},
                {name: 'username', type: 'text'},
                {name: 'password', type: 'text'},
                {name: 'api_key', type: 'text'},
                {name: 'active', type: 'integer'}
            ]
        }
    ]
});

app.factory.js

应用工厂.js

var appFactory = angular.module('app.factory', []);

appFactory.factory('DB', ['$q', '$cordovaSQLite', 'DB_CONFIG', function($q, $cordovaSQLite, DB_CONFIG) {

    var db = null;

    var init = function() {

        db = $cordovaSQLite.openDB({ name: DB_CONFIG.name });
        // I use this when testing in browser db = window.openDatabase(DB_CONFIG.name, '1.0', 'database', -1);

        _.each(DB_CONFIG.tables, function(table) {

            var columns = [];

            _.each(table.columns, function(column) {

                columns.push(column.name + ' ' + column.type);

            });

            var sql = 'CREATE TABLE IF NOT EXISTS ' + table.name + ' (' + columns.join(',') + ')';

            console.log('Table ' + table.name + ' initialized');

            query(sql);

        });

    };

    var query = function(sql, bindings) {

        bindings = typeof bindings !== 'undefined' ? bindings : [];

        return $cordovaSQLite.execute(db, sql, bindings);

    };

    var fetchAll = function(result) {

        var output = [];

        for (var i = 0; i < result.rows.length; i++) {
            output.push(result.rows.item(i));
        }

        return output;
    };

    var fetch = function(result) {
        return result.rows.item(0);
    };

    return {
        init: init,
        query: query,
        fetchAll: fetchAll,
        fetch: fetch
    };
}]);

login.config.js

登录配置文件

var loginConfig = angular.module('login.config', ['ionic', 'login.controller']);

loginConfig.config(function($stateProvider) {

    $stateProvider

        .state('login', {
            url: "/login",
            templateUrl: "modules/login/views/login.html",
            controller: 'loginController'
        });

});

login.controller.js

登录.controller.js

var loginController = angular.module('login.controller', []);

loginController.controller('loginController', ['$scope', '$state', 'DB', function($scope, $state, DB) {

    $scope.doLogin = function() {

        var username = this.username;
        var password = this.password;

        DB.query('SELECT * FROM users WHERE username = ? and password = ?', [username, password]).then(function(result){
            console.log(result);
        }, function(error){
            console.log(error);
        });

    };

}]);

The user has already been inserted into the database, and sometimes it works, and I get the results back, most times it doesn't, and I get the above mentioned error.

用户已经被插入到数据库中,有时它可以工作,我得到了结果,大多数时候它没有,我得到了上述错误。

I am assuming this is because the DB is not initialising in time, before I query the database?

我假设这是因为在查询数据库之前数据库没有及时初始化?

If so, is there a way that I can make 100% sure that the database has loaded before I query it?

如果是这样,有没有办法让我在查询之前 100% 确定数据库已加载?

回答by Elroy

I had the same issue, the DB does not initialize properly (This happens randomly), use promise with defer and $ionicPlatform.ready(function (){});

我遇到了同样的问题,数据库没有正确初始化(这是随机发生的),将 promise 与 defer 和 $ionicPlatform.ready(function (){}) 一起使用;

Reference: https://gist.github.com/borissondagh/29d1ed19d0df6051c56f

参考:https: //gist.github.com/borissondagh/29d1ed19d0df6051c56f

example:

例子:

angular.module('myapp.services', [])

.factory('DBA', function($cordovaSQLite, $q, $ionicPlatform) {
  var self = this;

  // Handle query's and potential errors
  self.query = function (query, parameters) {
    parameters = parameters || [];
    var q = $q.defer();

    $ionicPlatform.ready(function () {
      $cordovaSQLite.execute(db, query, parameters)
        .then(function (result) {
          q.resolve(result);
        }, function (error) {
          console.warn('DB error found');
          console.warn(error);
          q.reject(error);
        });
    });
    return q.promise;
  }

  // Process a result set
  self.getAll = function(result) {
    var output = [];

    for (var i = 0; i < result.rows.length; i++) {
      output.push(result.rows.item(i));
    }
    return output;
  }

  // Process a single result
  self.getById  = function(result) {
    var output = null;
    output = angular.copy(result.rows.item(0));
    return output;
  }

  return self;
})

回答by Avishai Peretz

i had same problem remove your sqlLite plugin and add it again problem solved!!!

我有同样的问题删除你的 sqlLite 插件并再次添加它问题解决了!!!

cordova plugin rm io.litehelpers.cordova.sqlite cordova plugin add io.litehelpers.cordova.sqlite

科尔多瓦插件 rm io.litehelpers.cordova.sqlite 科尔多瓦插件添加 io.litehelpers.cordova.sqlite

回答by Richard Long

$cordovaSQLite.openDB now requires a compulsory location parameter. Change

$cordovaSQLite.openDB 现在需要一个强制性的位置参数。改变

db = $cordovaSQLite.openDB({ name: DB_CONFIG.name });

to

db = $cordovaSQLite.openDB({ name: DB_CONFIG.name, location:'default' });

回答by user6608520

I had the same issue. Not sure why but it was somehow related to the keyboard plugin.

我遇到过同样的问题。不知道为什么,但它以某种方式与键盘插件有关。

Try:

尝试:

ionic plugin rm ionic-plugin-keyboard    
ionic plugin add ionic-plugin-keyboard

https://forum.ionicframework.com/t/important-all-ionic-users-please-update-your-keyboard-plugin/46889

https://forum.ionicframework.com/t/important-all-ionic-users-please-update-your-keyboard-plugin/46889

After doing this the database was working fine. 

这样做后,数据库工作正常。 

Edit:

编辑:

These commands have being update.

这些命令正在更新。

ionic cordova plugin rm ionic-plugin-keyboard
ionic cordova plugin add ionic-plugin-keyboard

回答by Koga

Try installing SqlLite again.

再次尝试安装 SqlLite。

ionic cordova plugin add cordova-sqlite-storage
npm install @ionic-native/sqlite

Had the same issue. Fixed by this.

有同样的问题。以此固定。

回答by Erwin Kraan

Maybe it will help if you open the connection only when you need it. You are keeping the connection open and maybe it timeout. What i normally do is that i open a connection than query what i need to query and than close the connection.

如果您仅在需要时打开连接,它可能会有所帮助。您保持连接打开,可能会超时。我通常做的是打开一个连接而不是查询我需要查询的内容而不是关闭连接。