Угловая фабрика возвращает ноль

0

Я пытаюсь создать базу данных на моей угловой фабрике:

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

Таким образом, возврат базы данных на моей фабрике возвращается неопределенно, но я не знаю, почему. Он должен возвращать базу данных, так как она правильно инициализирована.

Теги:

2 ответа

1
Лучший ответ

Вы не можете вернуть базу данных из функции, потому что получающая ее функция представляет собой асинхронный обратный вызов.

Вы можете использовать оператор return только в том случае, если вся функция синхронна (например, не работает асинхронная работа, например, чтение из файлов, подключение к базам данных, сетевые запросы, сокеты и т.д.).

В вашем случае window.sqlitePlugin.openDatabase выполняет некоторую асинхронную работу и запрашивает обратный вызов в качестве второго аргумента. Этот обратный вызов будет вызван после открытия соединения с базой данных, которое будет после getDatabase функции 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 second.

Если вы сделаете свой метод 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)

  • 0
    Огромное спасибо. Этот метод обратного вызова был идеальным решением.
0

Я думаю, вы должны заменить

var database = null;
var factory = {};

от

var factory = {};

и делай

return factory.database

в базе данных factory.getDatabase

Ещё вопросы

Сообщество Overcoder
Наверх
Меню