Worklight: синхронизация JSONStore и Angular rootScope

В настоящее время я использую Worklight 6.2 для разработки гибридного приложения для iOS, Android и Windows 8 благодаря Ionic Framework (на основе AngularJS). На данный момент я разработал большую часть своего приложения без каких-либо проблем, но сегодня я начал думать об использовании JSONStore для сохранения и защиты моих локальных данных (мое приложение можно использовать в автономном режиме).

Поэтому до сих пор я использовал области и корневую область Angular для обновления своей DOM благодаря привязке данных, как мы всегда делаем с Angular. Например, я создаю новый элемент с помощью HMI, и благодаря привязке данных мои объекты немедленно отображаются в моем приложении без необходимости что-либо перезагружать, а мои объекты Javascript обновляются последними значениями.

Теперь, когда я хочу подключить JSONStore, я столкнулся со следующей проблемой: каков наиболее последовательный и надежный способ для моего приложения синхронизировать JSONStore с моей корневой областью, чтобы каждый раз, когда я получаю новые обновления в своей области, JSONStore также обновляется и, таким образом, данные сохраняются и защищаются на устройстве (и готовы к синхронизации с моим бэкэндом).

Моя абсолютная ссылка должна быть JSONStore, так как это мое официальное надежное решение для постоянного хранения данных (и шифрования). Лучше всего, чтобы мое приложение использовало мою коллекцию JSONStore «в качестве корневой области», но, насколько я знаю, это невозможно сделать с Angular (на самом деле я не проверял, так как это звучит очень неправильно). В итоге я подумал, что мне нужно поддерживать 2 коллекции: мой JSONStore и мою корневую область. Это означает, что каждый раз, когда что-то изменяется в корневой области, я должен применить это к JSONStore. Чтобы упростить обслуживание, я думаю о наблюдении за основным объектом моей корневой области с помощью слушателя $watch, чтобы каждый раз, когда моя корневая область изменяется, я уничтожал свой JSONStore с последним значением моей корневой области. Что-то вроде этого :

$scope.$watch(function(){
    // Object to be watched
    return $rootScope.myObject;
}, function(newValue, oldValue){
    // Here, destroy the collection and init it again with the newValue object
});

Меня немного беспокоит производительность наблюдения за этим объектом в течение всего жизненного цикла моего приложения. Даже если объект не будет изменяться очень часто, объект может быть "довольно" большим (50kb). Кроме того, я не уверен, что JSONStore действительно нравится каждый раз уничтожать свои коллекции. Но не использовать это означало бы определять «места модификации» для обновления JSONStore каждый раз, когда в мою корневую область вносятся изменения. Это может сработать, но на самом деле не оптимально, так как нам нужно привыкнуть к дублированию исходного кода (1 для области видимости, 1 для JSONStore).

Ну, это беспокоит меня, потому что я не могу найти действительно жизнеспособное решение, поэтому, если у вас есть идеи/лучшие практики по этому поводу, не стесняйтесь поделиться!

Спасибо


person Jb Gartner    schedule 27.10.2014    source источник
comment
Не могли бы вы предоставить немного больше информации о том, чего вы пытаетесь достичь, используя обновление JSONStore так часто, как вы описали?   -  person Namfo    schedule 27.10.2014
comment
Как объяснено, на самом деле он не будет часто обновляться, просто его можно обновлять с множества разных страниц и контроллеров. Если вам нужен конкретный вариант использования: я вызываю свой адаптер при запуске приложения, отображаю элементы в списке. Я могу проверить каждый элемент, чтобы подтвердить их, нажав на кнопку. После проверки модель и представления обновляются, но затем мне нужно обновить JSONStore для синхронизации с тем, что у меня есть в моей области. Это то, что я хотел бы как-то автоматизировать, потому что тогда мне нужно синхронизировать мою коллекцию JSONStore с моим адаптером, чтобы сохранить мои данные на удаленном сервере.   -  person Jb Gartner    schedule 28.10.2014
comment
Возможно, вы уже пробовали это, но, возможно, вы можете сохранить экземпляры JSONStore в своей области и следить за этими изменениями в данных. Обновите эти изменения, когда они сработают.   -  person Namfo    schedule 28.10.2014


Ответы (2)


Способ сделать это - синхронизировать вашу область действия с JSONStore в «фоновом режиме» и извлекать данные, когда вам нужно, например: при запуске приложения.

Просмотр JSONStore потребует от вас запроса JSONStorage в функции просмотра, что было бы медленным и расточительным.

Как предложил @cnandreu, вы можете взаимодействовать с JSONStorage через службу angularjs.

Вот простая реализация с фоновой синхронизацией, взято из этой статьи

|| обратите внимание, что приведенный ниже код синхронизирует весь объект, тогда как, если ваш объект становится больше, я предлагаю выполнить некоторые функции добавления/обновления и удаления элементов в службе.||

В вашем контроллере:

// get the object
todoJsonStorage.get().then(function(res) {
    $scope.todos = res;
});

// synchronise in the background
$scope.$watch('todos', function (newValue, oldValue) {
        if (newValue !== oldValue) { // This prevents unneeded calls to the local storage
            todoJsonStorage.put(todos);
        }
    }, true);

Ваша служба выглядит примерно так:

/**
 * Services that persists and retrieves TODOs from Worklight JSON Storage
 */
angular.module('todomvc')
    .factory('todoJsonStorage', function ($q) {
        'use strict';

        var COLLECTION_NAME = 'todos';

        var collections = {
            todos: {
                searchFields: {title:'string', completed:'boolean'}
            }
        };

        var inited = false;

        //checks if inited and if not inits
        function initJSONStore(){
            var initDeferred = $q.defer();
            if (inited){
                initDeferred.resolve();
            } else {
                //Initialize the collection
                WL.JSONStore.init(collections).then(function () {
                    console.log("-> JSONStore init successful");
                    initDeferred.resolve();
                }).fail(function (errorObject) {
                    console.log("-> JSONStore error: " + errorObject.msg);
                });

                return initDeferred.promise;
            };
        }

        return {
            get: function () {
                var deferred = $q.defer();
                initJSONStore().then(function(){
                    WL.JSONStore.get(COLLECTION_NAME).findAll().then(function (res) {
                        if (res.length > 0){
                            deferred.resolve(JSON.parse(res[0].json.data || '[]'));
                        } else {
                            deferred.resolve(res);
                        }

                    }).fail(function (errorObject) {
                        console.log("JSONStore findbyid error: " + errorObject.msg);
                    });
                });
                return deferred.promise;
            },

            put: function (todos) {
                WL.JSONStore.get(COLLECTION_NAME).clear()
                WL.JSONStore.get(COLLECTION_NAME).add({data:JSON.stringify(todos)});
            }
        };

    });
person Gideon Simons    schedule 28.10.2014
comment
Хорошее дополнение к ответу Карлоса, Гидеон, спасибо за указатели. Я обязательно отмечу это как альтернативное решение, если не смогу найти эффективный способ синхронизации моего JSONStore с моей областью действия (другой способ не нужен) - person Jb Gartner; 28.10.2014
comment
Не беспокойтесь, синхронизация — это двусторонняя вещь :) .. поскольку это служба, вы также можете выполнять ту же фоновую синхронизацию, в то время как основной поддерживаемый объект — это служебная переменная, к которой затем могут привязываться все остальные контроллеры. - person Gideon Simons; 29.10.2014

Я недостаточно знаком с Angular.js, чтобы ответить на ваш вопрос.

Однако, для чего это стоит, это то, что я бы сделал:

  • Создайте Angular.js службу, которая обрабатывает все операции JSONStore.
  • Используйте внедрение зависимостей, чтобы получить доступ к службе внутри ваших контроллеров.
  • Следуйте документации по работа с внешними данными.

Я не ожидал, что этот сервис концептуально будет сильно отличаться от работы с REST API.

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

Ваш файл view.html будет определять текстовые поля и, возможно, кнопку сохранения (например, ng-click=save()). В вашем контроллере будет функция save(), которая будет вызывать службу jsonstore для сохранения нового документа пользователя. Когда вам нужно заполнить данные, вы должны вызвать что-то вроде этого в своем контроллере: myJSONStoreService.getPerson('carlos', successCallback), который выполнит WL.JSONStore.get('people').find({name: 'carlos'}).then(successCallback) и вернет результаты в файле successCallback.

В описанном мной сценарии нет привязки данных.

person cnandreu    schedule 27.10.2014
comment
Спасибо за совет Карлос. То, что вы описываете, на самом деле легко настроить, и это хороший способ хранения данных в JSONStore, но мне бы очень хотелось проверить, возможно ли получить автоматическую синхронизацию между моей областью и моим JSONStore, чтобы избежать необходимости явно скажем сейчас, сохраните в JSONStore поверх текущего контроллера, который у меня есть. Если по какой-либо причине разработчики забудут добавить инструкции по добавлению в JSONStore, данные будут отображаться в пользовательском интерфейсе (поскольку они доступны в области), но не на постоянном уровне данных. Может быть, я захожу слишком далеко, но я хотел бы посмотреть, смогу ли я автоматизировать все это. - person Jb Gartner; 28.10.2014