Angular Factory返回null

时间:2015-11-06 10:16:59

标签: javascript angularjs

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

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

因此我工厂中数据库的返回返回undefined,但我不知道原因。它应该返回数据库,因为它已正确初始化。

2 个答案:

答案 0 :(得分:1)

您无法从函数返回数据库,因为接收它的函数是异步回调。

如果整个函数是同步的,则只能使用return语句(例如,不进行任何异步工作,例如从文件读取,连接到数据库,网络请求,套接字等)。 / p>

在您的情况下,window.sqlitePlugin.openDatabase执行一些异步工作和asks for a callback as the second argument。在数据库连接打开后将调用此回调,这将在您的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

答案 1 :(得分:0)

我认为你应该替换

var database = null;
var factory = {};

通过

var factory = {};

并做

return factory.database
工厂中的

.getDatabase