Рубрики
Без рубрики

Сохранение угловых «сервисных» данных списка в синхронизации с контроллерами

Целью данного поста направлена на услуги, которые проводят коллекции, которые обновляют от удаленных вызовов данных.

Автор оригинала: Justin Obney.

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

В Angularjs существует множество важно для разделения опасений. Одним из наиболее практичных узоров для проведения состояния приложения является перемещение этих данных в угловые услуги или фабрики. Какой из первых для использования является совершенно личным предпочтением, на мой взгляд (я выбираю за фабрики большую часть времени).

Целью данного поста направлена на услуги, которые проводят коллекции, которые обновляют от удаленных вызовов данных.

Целевая версия Angularjs во время написания: 1.2.19

Слишком много раз, я бежал через угловые контроллеры, приносящие $ Scope Сервис только к $ смотреть Сборная службы:

Плохо:

app.controller('Ctrl1', function($scope, DataFactory) {
  // bind the controller property to the service collection
  this.items = DataFactory.items;
  
  // watch the collection for changes
  $scope.$watch(watchSource, function(current, previous){
    this.items = current;
  });
  
  function watchSource(){
    return DataFactory.items;
  }  
});

app.factory('DataFactory', function($q, $timeout) {
  var svc = {};
  svc.items = [];

  svc.getDataStream = function() {
    
    var fakeData = [
      { id: 1, name: 'name 1' },
      { id: 2, name: 'name 2' },
      { id: 4, name: 'name 4' }
    ];
    
    // using $q to fake async data grab
    return $q.when(fakeData)
      .then(function(data) {
        svc.items = data;
      });
  };

  return svc;
});

Я знаю, что вы думаете: «Почему это просто не работает по умолчанию?» Мы явно обновляем Datafactory.items Отказ

svc.getDataStream = function() {
  return $q.when(fakeData)
    .then(function(data) {
      // here we are clearly reseting the data
      // to the response of the call.. Why doesn't
      // it just databind?
      svc.items = data;
    });
};

Причина, по которой угловые не «смотрит» это значение, это потому, что когда он устанавливает неявную $ смотреть С точки зрения, он ссылается на оригинальный массив из Datafactory Отказ Но когда данные возвращаются через $ http он заменяет свойство с другой справочностью на массиве. Таким образом, угловой не может посмотреть коллекцию без добавления противных $ смотреть Функции в ваших контроллерах.

Так почему же $ Watch. Плохая вещь в контроллере?

Он добавляет к познавательной нагрузке, необходимой для понимания того, что происходит в контроллере. Когда мы смотрим на код, что другие (или самые 6 месяцев) писали, возможность легко понять что не тратя много времени, разборки Как очень выгодно Любые привязки в вашем представлении вызывают неявные часы для установки. Также все $ смотреть Функции выполняются для каждого $ digest что может произойти много раз в «диватовом цикле» (угловые пинает их с большинством взаимодействий). Добавление еще одного часа – это шаблон, который может привести вас к проблемам производительности в будущем.

Конечно, мы можем удалить зависимость на $ Scope Просто чтобы посмотреть эту коллекцию. Давайте посмотрим на очень простой пример этого разделения, адаптированные из Девиз Тоддо Отказ

Лучшее:

app.controller('Ctrl1', function(DataFactory) {
  // bind the controller property to the service collection
  this.items = DataFactory.items;

  // invoke the call to get data
  DataFactory
    .getDataStream()
    .then(function() {
      // update the controller collection property
      this.items = DataFactory.items;
    }.bind(this));
});

// sample "service" for getting data
app.factory('DataFactory', function($q, $timeout) {
  var svc = {};
  svc.items = [];

  svc.getDataStream = function() {
    
    var fakeData = [
      { id: 1, name: 'name 1' },
      { id: 2, name: 'name 2' },
      { id: 4, name: 'name 4' }
    ];
    
    // using $q to fake async data grab
    return $q.when(fakeData)
      .then(function(data) {
        svc.items = data;
      });
  };

  return svc;
});

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

Как насчет этого:

app.controller('Ctrl1', function(DataFactory) {
  // bind the controller property to the service collection
  this.items = DataFactory.items;
 
  // but wouldn't it be so much better
  // to just call it and let it work
  DataFactory.getDataStream();
});

Разве это просто читает так много чище?

Введите angular.Copy Отказ Что angular.Copy Предполагается, что при задании нового массива и массив источника пустое источника (настроив длину до 0 Я думаю, что …), а затем вытесните массив с новыми элементами массива.

Наш конечный результат:

var app = angular.module('app', []);

app.controller('Ctrl1', function(DataFactory) {
  this.items = DataFactory.items;

  DataFactory.getDataStream();
});

app.controller('Ctrl2', function($timeout, DataFactory) {
  // when this eventually fires and gets *remote* data again
  // our other controller will automatically sync up
  // without the need for the $watch function
  $timeout(DataFactory.getDataStream, 2000);
});

app.factory('DataFactory', function($q) {
  var svc = {};
  svc.items = [];

  svc.getDataStream = function() {
    
    var fakeData = [
      { id: 1, name: 'name 1' },
      { id: 2, name: 'name 2' },
      { id: 4, name: 'name 4' }
    ];
    
    // using $q to fake async data grab
    return $q.when(fakeData)
      .then(function(data) {
        // this is the magic
        angular.copy(data, svc.items);
      });
  };

  return svc;
});

Эта статья была первоначально опубликована на мой блог .