Задать вопрос

AngularJS, синхронизация данных с сервера и модели после "Экшенов"

Реализую админку для проекта. Список материалов (в данном случаи "новостей") в виде таблицы с двумя "экшенами" (edit и remove).

dea26565988d7a6416df6c2c55dc888a.jpg

Вьюха:
<tr ng:repeat="item in items">
        <td>{{ item.news_id }}</td>
        <td>{{ item.news_preview|truncate:20 }}</td>
        ...
        <td>
            <i class="square small inverted edit icon" ng:click="editAction(item)"></i>
            <i class="square small inverted remove icon" ng:click="deleteAction(item)"></i>
        </td>
    </tr>


Модель (хотя это и не модель, но пока в процессе обучения пойдет, обычно называют Фэктори), приведина в соответсвие с методами RESTful контроллера Laravel 4:
angular.module('backendApp.services')
    .service('NewsModel', function ($resource, PATH_API) {

        return $resource(PATH_API + 'news/:param1/:param2', {}, {
            index  : { method: 'GET', isArray: true },
            create : { method: 'GET', params: {param1: 'create'} },
            store  : { method: 'POST' },
            show   : { method: 'GET', params: {param1: '@id'} },
            edit   : { method: 'GET', params: {param1: '@id', params: 'edit'} },
            update : { method: 'PUT', params: {param1: '@id'} },
            destroy: { method: 'DELETE', params: {param1: '@id'} }
        });

    });


Контроллер:
angular.module('backendApp.controllers')
    .controller('NewsListController', function ($rootScope, $scope, $routeSegment, $location, PATH_API, NewsModel, $notification) {

        $scope.items = NewsModel.index();

        $scope.deleteAction = function (item) {
            var selfItem = item,
                lastData = null;

            NewsModel.destroy({param1: selfItem.news_id}, function () {

                // "Мягко" удаляем запись. Без ресета данных модели.
                $scope.items.splice($scope.items.indexOf(selfItem), 1);

                // Получаем с сервера актуальное состояние и сравниваем.
                // Синхронизируем, если есть различия.
                lastData = NewsModel.index(function () {
                    if (!angular.equals($scope.items, lastData)) {
                        // Запускаем нотификацию
                        $notification.info('Синхронизация данных');
                        // Обновляем модель (hard reset model).
                        $scope.items = lastData;
                    }
                });
            });
        };
    });


Пока писал, уже решил вопрос. Тем не менее возник другой вопрос.
Ситуация: в один момент время контент редактирую два человека, один добавляет Новосить (с ID 7) и удаляет с ID 5 например. А другой ни чего не делает и весит на таблице. Естественно у него не актуальная информация и он начинает удалять Новость с ID 3. (Реализовано, там где коммент hard reset model) У него "дергает" (не просто проподают элементы удаленные, а вообще все удаляется и рендерится по новой) таблицу потому, что модель полность заменина из за того, что angular.equals($scope.items, lastData) вернул false. Так же не реализован случай когда кликают на удаление Новости, которая уже удалена. Идея думаю ясна. Кто как решает подобную проблему? Гуглу даже не знаю как задать вопрос.
  • Вопрос задан
  • 5699 просмотров
Подписаться 5 Оценить Комментировать
Решения вопроса 1
@zloyusr
alexiusp, я думаю автора интересовал именно вопрос синхронизации данных между несколькими клиентами.
Вопрос действительно не простой, и в первую очередь надо решить необходимо ли вам это. В вашем приложении действительно критично то, что два клиента могут одновременно редактировать одну запись? Если так, то рекомендую ознакомиться со статьями на тему "параллельное редактирование" (начать можно прямо с Habrahabr'a), а также с библиотекой ShareJS.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
alexiusp
@alexiusp
senior frontend developer
По поводу синхронизации при удалении.
Вариант 1: затемнять или вообще скрывать область таблицы на время синхронизации, чтобы "дёргание" не вызывало вопросов у пользователя
Вариант 2: вместо $scope.items = lastData; делать обход массива, сравнивать полученные с сервера значения с имеющимися и менять, если есть чего.

Очевидно, что второй вариант затратнее по ресурсам и вообще не слишком привлекателен. Если одновременно сидит два пользователя и изменилось две строки в таблице - это будет красиво, но если пользователей больше и изменений больше дёргание всё равно произойдёт из-за радикального изменения содержимого.

Можно, на крайний случай, попытаться делать не радикальное приравнивание массивов, а построчное - может быть это немного сгладит картинку.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы