Angular Factory returns null

Angular Factory returns null

本文关键字:null returns Factory Angular      更新时间:2023-09-26

我正试图在我的角度工厂中建立一个数据库:

angular.module("App")
.factory("DatabaseFactory", function () {
    var database = null;
    var factory = {};
    factory.getDatabase = function () {
        if (database == null) {
            window.sqlitePlugin.openDatabase({
                name: "myDB.db",
                androidDatabaseImplementation: 2,
                androidLockWorkaround: 1
            }, function (db) {
                database = db;
                database.transaction(function (transaction) {
                    transaction.executeSql(create_user, [], function (transaction, result) {
                        console.log("table user created: " + JSON.stringify(result));
                    }, function (error) {
                        console.log("table user error: " + error.message);
                    });
                }, function (error) {
                    console.log("transaction error: " + error.message);
                }, function () {
                    console.log("transaction ok");
                    return database;
                });
            });
        } else {
            return database;
        }
    }
    return factory;
});

数据库的创建工作正常,事务也可以。我现在提供了一个带有初始化数据库功能的服务:

angular.module("App")
.service("DatabaseService", function (DatabaseFactory) {
    var database;
    function initDatabase() {
        console.log("init before database: " + JSON.stringify(database));
        database = DatabaseFactory.getDatabase();
        console.log("intit after database: " + JSON.stringify(database));
    }
    return {
        initDatabase: function () {
            initDatabase();
        }
    };
});

它在设备上被调用:

angular.module("App", ["ionic", "ngCordova", "App.Home"])
.config(function ($stateProvider, $urlRouterProvider) {
    $stateProvider.state("app", {
        url: "/app",
        abstract: true,
        templateUrl: "templates/main.html"
    });
    $urlRouterProvider.otherwise("/app/home");
})
.run(function ($rootScope, $ionicPlatform, DatabaseService) {
    $ionicPlatform.ready(function () {
        console.log("ionic Ready");
        if (window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if (window.StatusBar) {
            StatusBar.styleDefault();
        }
        DatabaseService.initDatabase();
    });
});

日志输出:

init before database: + undefined
init after database: + undefined

所以我工厂中数据库的返回返回未定义,但我不知道为什么。它应该返回数据库,因为它已正确初始化。

您不能从函数返回数据库,因为接收数据库的函数是异步回调。

只有当整个函数是同步的(例如,不做任何异步工作,例如从文件读取、连接到数据库、网络请求、套接字等)时,才能使用return语句。

在您的情况下,window.sqlitePlugin.openDatabase执行一些异步工作,并请求回调作为第二个参数。此回调将在数据库连接打开后调用,也就是在getDatabase函数返回值后调用。

window.sqlitePlugin.openDatabase({
  name: "myDB.db",
  androidDatabaseImplementation: 2,
  androidLockWorkaround: 1
}, function (db) {
  database = db
  // this happens at some point in the future
});
// this happens straight away
// at this point database is still undefined
return database;

测试这一点以供将来参考的一个好方法是使用console.log来查看代码在什么时间以什么顺序运行。

window.sqlitePlugin.openDatabase({
  // ...
}, function (db) {
  database = db
  console.log('A');
});
console.log('B');
return database;

您会看到,不是按照语句的编写顺序执行,而是先记录B,然后再记录A

如果使getDatabase方法采用回调参数,则可以在db对象准备好后立即将其传递给它。

factory.getDatabase = function (callback) {
  window.sqlitePlugin.openDatabase({
    // ...
  }, function (db) {
    // do some stuff with db, when you are ready
    // pass it to the callback, with null as the
    // first argument (because there isn't an error
    callback(null, db);
  });

然后,您将重写代码以利用回调。

DatabaseFactory.getDatabase(function(err, db) {
  console.log("intit after database: " + JSON.stringify(database));
});

您可能想知道为什么回调也有err参数。

在node.js中,通过将异步函数中的错误作为第一个参数返回到当前函数的回调来处理这些错误被认为是标准做法。如果出现错误,则会向第一个参数传递一个包含所有详细信息的error对象。否则,第一个参数为null。

(来自NodeJitsu)

我认为你应该更换

var database = null;
var factory = {};

通过

var factory = {};

并进行

return factory.database

在您的工厂中。getDatabase