Создание огроооомных приложений на AngularJS

Original author: Брайан Форд
  • Translation
  • Tutorial
Документация по Ангуляру отлично подходит для начала работы и ковыряния в API. Однако, она не объясняет как организовать и управлять приложением, когда оно разрастется до десятков или сотен тысяч строк кода. Я собрал здесь некоторые из моих наблюдений и передового опыта по управлению расползающимися приложениями. Сначала взглянем на организацию, затем перейдем к некоторым советам по улучшению производительности и закончим краткой сводкой по инструментам, серверам и процессу сборки. Этот пост будет сосредоточен на больших приложениях, в частности, есть отличная статья по лучшим практикам AngularJS с декабрьской встречи, на которую также стоит взглянуть.

Не пишите огромные приложения


Лучший совет по огромным приложениям не делать их. Пишите небольшие сфокусированные модульные части и постепенно объединяйте их в более крупные вещи, чтобы собрать приложение. (Этот совет дал хакер node.js, крутой, во всех отношениях, чувак @substack).

Организация


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

Каталоги

Типичная рекомендуемая мной структура папок:

root-app-folder
├── index.html
├── scripts
│   ├── controllers
│   │   └── main.js
│   │   └── ...
│   ├── directives
│   │   └── myDirective.js
│   │   └── ...
│   ├── filters
│   │   └── myFilter.js
│   │   └── ...
│   ├── services
│   │   └── myService.js
│   │   └── ...
│   ├── vendor
│   │   ├── angular.js
│   │   ├── angular.min.js
│   │   ├── es5-shim.min.js
│   │   └── json3.min.js
│   └── app.js
├── styles
│   └── ...
└── views
    ├── main.html
    └── ...

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

На тему организации кода читайте так же Организация кода в больших AngularJS и JavaScript приложениях (прим. переводчика)

Файлы

Каждый файл должен содержать одну «сущность», где «сущность» представляет собой контроллер, директиву, фильтр или сервис. Это позволяет, как минимум, сфокусировать файлы. Также помогает создать лакмусовую бумажку для тестирования API. Если обнаружили, что листаете файлы вперед и назад слишком часто, это признак того, что ваши API-интерфейсы слишком сложные. Необходимо переосмыслить, реорганизовать и упростить их.

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

Модули

Определяйте и настраивайте все модули в app.js
:

angular.module('yourAppName', ['yourAppDep']);
angular.module('yourAppDep');

Определяйте контроллеры, сервисы и т.д. в модулях следующим образом:

angular.module('yourAppDep').controller('MyCtrl', function () {
  // ...
});

Хотя мы (команда Ангуляра) обсуждали возможность ленивой загрузки модульной структуры, она еще не входит в планы следующей версии Ангуляра. Было хорошее обсуждение на Google+ об использовании составных высокоуровневых приложений приложения для достижения эффекта ленивой загрузки. Не пробовал так делать, но если отчаянно нуждаетесь в уменьшении размера полезной нагрузки, что, безусловно, там показан один из способов.

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

Зависимости

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

API-интерфейсы должны быть многоуровневыми. Не следует разносить контроллеры по разным уровням абстракции.

Директивы

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

Например, если ваше приложение называется «The Best Todo List App Ever», можете начинать директивы с префикса «btla».

angular.module('yourAppDep').directive('btlaControlPanel', function () {
  // ...
});

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

Сервисы

angular.module('yourAppDep').service('MyCtrl', function () {
  // ...
});

Модели

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

Если используете NoSQL хранилища данных, такие как CouchDB или MongoDB, можно будет использовать в качестве контента чистые JavaScript-объекты (POJO) и функциональных помощников. Если используете реляционную базу данных, как MySQL, можете использовать псевдо-классы с методами мутации, сериализации и десериализации данных. Если сервер предоставляет RESTful-интерфейс, сервис $resource станет хорошей площадкой для начала. Это всего лишь предложения, любые из этих подходов могут быть полезны вне ситуаций, которые описал. Вариантов так много, что иногда сложно принять решение. Но раздумья об организации данных окупятся.

В основном, можно найти много отличных инструменты для работы с моделями в Underscore.js, библиотеке, которая также используется в Backbone.js.

Контроллеры

По соглашению, имена контроллеров должны начинаться с заглавной буквы и заканчиваться на "Ctrl".

angular.module('yourAppDep').controller('MyCtrl', function () {
  // ...
});

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

Производительность


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

Оптимизация цикла переваривания (digest)

Ангуляр использует грязную проверку в цикле «переваривания». Непосвященные могут прочитать больше о цикле переваривания в официальной документации и в этом ответе на StackOverflow.

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

app.factory('socket', function ($rootScope) {
  var socket = io.connect();
  return {
    on: function (eventName, callback) {
      socket.on(eventName, function () {  // может происходить много раз в секунду
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(socket, args);
        });
      });
    }
    // ...
  };
});

Один из отличных способов справиться с этим, это «задушить» запросы, чтобы запускать переваривание лишь несколько раз в секунду. Underscore.js предоставляет такую функцию, но её реализация миниатюрна, так что воспроизвел ее внутри сервиса socket ниже:

app.factory('socket', function ($rootScope) {

  // Underscore.js 1.4.3
  // http://underscorejs.org
  // (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
  // Underscore may be freely distributed under the MIT license.

  // _.throttle
  // https://github.com/documentcloud/underscore/blob/master/underscore.js#L626
  // Returns a function, that, when invoked, will only be triggered at most once
  // during a given window of time.
  var throttle = function (func, wait) {
    var context, args, timeout, result;
    var previous = 0;
    var later = function() {
      previous = new Date();
      timeout = null;
      result = func.apply(context, args);
    };
    return function() {
      var now = new Date();
      var remaining = wait - (now - previous);
      context = this;
      args = arguments;
      if (remaining <= 0) {
        clearTimeout(timeout);
        timeout = null;
        previous = now;
        result = func.apply(context, args);
      } else if (!timeout) {
        timeout = setTimeout(later, remaining);
      }
      return result;
    };
  };

  var socket = io.connect();
  return {
    on: function (eventName, callback) {
      socket.on(eventName, throttle(function () {  // ограничиваем до одного раза в 500 мс
        var args = arguments;
        $rootScope.$apply(function () {
          callback.apply(socket, args);
        });
      }, 500));
    }
    // ...
  };
});

Так же известно, что входящие изменения влияют только на определенные области и можно провести грязную проверку только для них. В подобных случаях можно вызвать $scope.$digest вместо $scope.$apply. $digest сработает только для области видимости, в которой он вызван и для всех дочерних областей видимости.

Наконец, чтобы поддерживать циклы переваривания короткими, выражения в $scope.$watch должны быть как можно более быстрыми. По возможности, избегайте глубоких сравнений. Помните, что необходимо всего лишь сравнивать вещи, влияющие на вид.

Фильтры

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

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

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

{{someModel.name | titlecase}}

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

angular.module('myApp').controller('MyCtrl', function ($scope, $http, $filter) {
  $http.get('/someModel')
    .success(function (data) {
      $scope.someModel = data;
      // применяем тот же самый фильтр «titlecase» внутри контроллера после загрузки данных
      $scope.someModel.name = $filter('titlecase')($scope.someModel.name);
    });
});

В случаях, когда невозможно преобразовать данные во время выборки, запоминание будет лучшим способом ускорения дорогостоящих фильтров без особого труда. Адди Османи написал довольно большую статью о запоминании в JavaScript, которую стоит прочесть. Что касается реализации, Underscore.js предоставляет отличные запоминающие функции, которые можно использовать. Однако, этим методом не следует пользоваться вслепую. Запоминание помогает только при частых вызовах одного и того же фильтра без изменения модели. Для быстро меняющихся моделей, значения в которых слишком разнятся во время выполнения приложения, лучше не использовать запоминающие фильтры для таких данных.

Так же пару советов по оптимизации, можно прочитать здесь (прим. переводчика)

Тестирование


Тестирование чрезвычайно важно для больших проектов. Тесты позволяют уверенно проводить рефакторинг, который имеет важное значение для сохранения чистоты кода в большом проекте. В больших приложениях должны проводится как модульные, так и системные (E2E) тесты. Модульные тесты помогают выявить проблемы, а системные — убедиться, что всё приложение работает как ожидалось. Каждый контроллер, сервис, фильтр и директива должны иметь набор модульных тестов. Каждая особенность приложения должна иметь системный тест.

Это еще одна тема, заслуживающая большого внимания. К счастью, документация Ангуляра может многое сказать как о модульных, так и о сисемных тестах. Мой коллега Войта Джин также рассказывал недавно о тестировании директив. Безусловно, стоит посмотреть его видео.

Инструментарий


Я проделал кучу работы по Yeoman, чтобы попытаться выделить лучшие практики и хорошую структуру проекта, и сделать автоматическую генерацию небольших шаблонных библиотек Ангуляра. Настоятельно рекомендую воспользоваться этим.

Batarang еще один из моих проектов, который подходит для отладки и поиска узких мест в производительности.

Сервер


Как известно, с Ангуляром можно использовать любой сервер, какой захотите. Это строго клиентская библиотека. Моей рекомендацией и предпочтительной установкой является использование Node.js вместе с Nginx. Использую Nginx как сервер статических файлов, и Node.js для создания RESTful API и/или сокет приложения. Node.js это золотая середина между простотой использования и скоростью. Например, относительно легко порождать рабочие процессы или создать веб-сервер, который может использовать все ядра воображаемого сервера.

Что касается облачных сервисов, с большим успехом использовал и Nodejitsu и Linode. Nodejitsu предпочтителен, если строго придерживаетесь Node.js. Он облегчает развертывание приложения, и вам не придется беспокоиться о серверной среде. Можно порождать дополнительные процессы Node.js, необходимые для расширения и чтобы выдерживать большую нагрузку. Если необходим больший контроль над серверной средой, Linode предоставляет доступ к корню парка виртуальных машин. Linode также обеспечивает хороший API для управления виртуальными машинами. Существует множество других отличных поставщиков облачных сервисов, которые еще не успел испытать на себе.

Настройка и масштабирование серверной части достойна отдельной статьи, и нет недостатка хороших советов в других местах.

Процесс сборки


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

На данный момент, думаю, что сперва лучше всего объединить яваскрипт-файлы с app.js, затем с помощью ngmin закомментировать функции внедрения зависимости, и, наконец, минифицировать с помощью Closure Compiler с флагом --compilation_level SIMPLE_OPTIMIZATIONS. Можете посмотреть пример в работе в процессе сборки angular.js.

Не рекомендую использовать RequireJS с Ангуляром. Хотя это, конечно, возможно, я не видел ни одного случая, когда применение RequireJS было бы выгодно на практике.

Заключение


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

Есть несколько советов по масштабированию ангуляр-приложений? Пишите в твиттер, на электронную почту, или отправьте пулл-реквест на Гитхабе.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 38

    –2
    Уже в который раз вижу это слово «Ангуляр» и каждый раз оно меня бесит. Почему не Angular?
    translate.google.com.ua/translate_tts?ie=UTF-8&q=Angular&tl=en&total=1&idx=0&textlen=7&prev=input&sa=N
      0
      Тогда можно и как Энгюлё транскрибировать :-) Ангуляр, потому что статья русская и понятие читателем хорошо знакомо, как и ява-скрипт и твиттер. Не перевожу только незнакомые понятия. А, вообще, тут такое дело, приживется так, как всюду публикуется. Сделайте сотню переводов без транскрипции, приживется оригинальное название.
      • UFO just landed and posted this here
          +2
          А я не люблю, когда переводы пытаются учить произношению. В русских текстах по возможности должна использоваться кириллица.

          Имена собственные объектом перевода не являются. Они являются объектом локализации.

          Автору +500 за «Ангуляр» и «яваскрипт». «Restful» не является именем собственным, и посему перевод уместен.
          Названия библиотек слова неудобные, но всегда можно что-то придумать. Не вижу проблем писать «ноде» и «андерскор».
          А тот, кто сказал джитхаб, должен подучить матчасть на тему произношения слова git.
            –4
            Вы наверное без ума от 1С :)
            +2
            Не хотел бы я жить в мире, где аспирин, памперс, джип, лимонад и т. п. пишутся и произносятся как в оригинале. ХТМЛ и ПХП, кстати, отлично прижились, Гитхаб тоже, просто забыл его транскрибировать. В русском тексте любые слова подчиняются правилам русского языка и никак иначе, а то получается такое
              0
              Так же как «ява-скрипт» это Ваше «ангуляр» звучит корявенько, если до этого слышал в основном англоязычное произношение.

              А я вот сейчас послушал по вашей ссылки и для меня английское звучит странненько. А вообще мы на русскоязычном ресурсе общаемся на русском. Чем меньше слов на других языках (не путать с заимствованными) тем проще общаться.
          +9
          Документация <ваша-любимая-MV*-библиотека> отлично подходит для начала работы и ковыряния в API. Однако, она не объясняет как организовать и управлять приложением, когда оно разрастется до десятков или сотен тысяч строк кода.
            –2
            Тогда можно и как Энгюлё транскрибировать :-) Ангуляр, потому что статья русская и понятие читателем хорошо знакомо, как и ява-скрипт и твиттер. Не перевожу только незнакомые понятия. А, вообще, тут такое дело, приживется так, как всюду публикуется. Сделайте сотню переводов без транскрипции, приживется оригинальное название.
              +1
              digest

              переваривания? вы серьезно?
                +1
                В качестве эксперимента :-) Слишком часто встречающееся понятие, чтобы оставить как есть. Дайджест в русском имеет несколько другой смысл. Переваривание вполне подходит по смыслу. Думаю, после нескольких прочтений перестанет резать глаз.
                  0
                  Суть процесса описывается словом «сведение», как на мой взгляд. Но в общем попытка внести какой-то конкретный вариант термина редко удается.
                    0
                    Цикл сведения… Можно подумать. Попытка всегда удается, это дело времени. Почитайте, например, основы операционных систем. Там и семафоры и потоки и мьютексы. Дисциплина устоявшаяся, поэтому всем понятиям давно подобраны русские варианты.
                    0
                    «Переваривание»… цикл переваривания…

                    Смотря на Oxford Dicr(раз уж нужно переводить этот термин, мдя):
                    a compilation or summary of material or information

                    Digest cycle:
                    compilation of information |+ in cycle

                    Ух, ты, из доков:
                    Processes all of the watchers of the current scope and its children. Because a watcher's listener can change the model, the $digest() keeps calling the watchers until no more listeners are firing. This means that it is possible to get into an infinite loop. This function will throw 'Maximum iteration limit exceeded.' if the number of iterations exceeds 10.

                    Точно нет более вменяемого аналога?
                  +1
                  Раз уж пост про Angular может кто-нибудь может посоветовать, что делать с моделями. После Backbone я в упор не могу понять, как организовать работу с реально-имеющимися моделями, я имею ввиду следующее: у меня есть данные, хранимые в LocalStorage, они некоотрым образом связаны, например, пользователи и совершенные платежи. В Backbone есть понятная сущность модель, есть коллекции, там же я реализую необходимые мне методы, используя плагин реализующий работу Backbone.sync с LocalStorage мои данные будут дегко и просто сохраняться и загружаться из него. Я могу подписаться на изменения модели, и перегенерировать некоторые другие сущности, например, список дней, когда были хоть какие-то платежи, для вывода в view.

                  В Angular, я не вижу ничего, на основе чего строить модели, я могу, конечно, в html написать у инпута, что ng-model='user.name', но как описать саму модель, реализовать её методы непонятно. Пока я так понял, как на Angular построить интерефейс, это действительно легко и просто, так же как и реализовать RESTfull для работы с backend'ом, но вопрос как построить толстые клиент с собственной логикой работы с коллекциями и моделями остается открытым.

                  Пока я так понимаю, это попросту должно быть реализовано другими средствами, но какими непонятно. В поисках коллекций нашелся плагин angular-collection, но это не решает проблем.
                    0
                    Если разберетесь, напи́шите топик?
                      0
                      Меня не покидает ощущение, что все должно быть как-то просто. Если же будет о чем написать, то обязательно напишу, правда я тут еще один топик задолжал, так что все наджеды на то, что летом будет время
                      0
                      Только вчера нашел сыроватый пример angulario.com/, там в демке что-то есть про куки, сессии и LocalStorage. Пока не разбирался.

                      Реализацию методов, думаю, можно подсмотреть в сервисе $resource, там каждый объект модели имеет в прототипе методы управления собой. Если правильно понял о чем речь.
                        0
                        Интересно, я думаю можно найти много интересного. Насчет LocalStorage надо посмотреть, что же все-таки делает плагин Offline Mode, так как написано что он сохраняет запросы когда нет сети, чтобы отправить позже, что не совсем тоже самое, что когда приложение в принципе может работать в офлайне, т.е реализована нужная логика, а бекенд нужен лишь для сохранения данных.

                        По вашему совету $resourse, кстати нагуглился плагин angularjs-webstorage-resource, он, конечно, сырой, но может прояснить некоторые моменты, как все-таки это дело организовать.
                        +1
                        Вы хотите что-то типа такого? Или что-то другое?

                        'use strict';
                        
                        angular.module('app.api.entities.user', ['app.api.rest.user'])
                        
                        .factory('User', function($q, UserApi) {
                            var cache = {};
                        
                            var initObject = function(data) {
                                if (cache[data.id]) {
                                    angular.extend(cache[data.id], new User(data));
                                } else {
                                    cache[data.id] = new User(data);
                                }
                                return cache[data.id];
                            };
                        
                            var User = function(data) {
                                angular.extend(this, data);
                            };
                        
                            User.get = function(id){
                                var apiResult = UserApi.get(id).then(function (test) {
                                    return initObject(test);
                                });
                        
                                if (cache[id]) {
                                    return $q.when(cache[id]);
                                } else {
                                    return apiResult;
                                }
                            };
                        
                            User.getAll = function(options){
                                return UserApi.getAll(options).then(function(tests){
                                    return _.map(tests, function(test){ return initObject(test); });
                                });
                            };
                        
                            User.create = function(params){
                                return UserApi.create(params);
                            };
                        
                            User.prototype.remove = function(){
                                return UserApi.remove(this.id);
                            };
                        
                            return User;
                        });
                        


                        Здесь в качестве примера сделано кэширование в памяти, если объект есть в кэше, он оттуда и отдается и делается фоновое обновление.
                        Естественно, кому что надо, тот то и делает, хоть localStorage, хоть что угодно. Ну и немного прослеживается структура приложения, точнее его части.

                        Полуживой пример: jsfiddle.net/u5gV2/
                          0
                          Спасибо! Ваш пример многое проясняет.
                          В целом решение очень похоже на то, что нужно, но как можно заметить, по сути вы описываете модель и все её методы с нуля, так же и API, а сверху добавляете лишь обертку от Angular, чтобы использовать далее. Или я чего-то не улавливаю и Angular как-то дополняет поведение созданных объектов?

                          Дальше, если я хочу подписаться на изменения в модели, то мне надо положить её в $scope и использовать $watch. Подписаться на изменнения коллекции или модели, я так понимаю непосредственно нельзя, или я ошибаюсь?
                            0
                            Я бы не назвал это оберткой. Хотя смотря что под этим подразумевать. Это сервис, который потом может инжектироваться в другие сущности AngularJS (контроллеры, другие сервисы, директивы, фильтры). Но инжектироваться будет вполне себе обычный объект javascript. Еще можно отметить, что сервисы в Angular — синглтоны.

                            Писать можно с нуля, можно использовать $resource, можно свою какую-нибудь project-специфичную фабрику сделать.

                            Про подписки — смотря зачем Вам надо подписываться. Подписаться, в принципе, можно и так:
                            $scope.$watch(function(){
                                return SomeService.something
                            }, function(newVal, oldVal){
                                
                            }, true);
                            

                            Но в документации это, вроде, нормально освещено.
                              0
                              Этот раздел документации я видел, я про то, что это делается через $scope, а не через сам объект myObject.bind(...).

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

                              С $resource ситуация интересная, но если посмотреть на тот же angularjs-webstorage-resource видно, что это не то, чтобы путь предлагаемый фреймворком, в том плане, что не совсем гладко все проходит.

                              Спасибо вам, ситуация немного прояснилась, мне не так много надо, так что думаю этого всего хватит.
                                0
                                Этот раздел документации я видел, я про то, что это делается через $scope, а не через сам объект myObject.bind(...).

                                Ну да, там dirty checking (Conceptual Overview).

                                Получается, что как я и предлагал AngularJS не предлагает конкретных инструментов для описания моделей и коллекций

                                Я не очень понял, а зачем они Вам?

                                С $resource ситуация интересная

                                $resource я практически никогда и не использую (в текущих проектах тоже не используем). То, что я привел в качестве примера, конечно, напоминает базовый набор CRUD, но это в том числе потому, что я оттуда выпилил всю специфику проекта. А так там и API гораздо богаче и .get навороченнее и много чего еще всякого специфичного. Единственное, что я делал, условно говоря, на базе $resource — это похожую фабрику немного для других целей.
                                  0
                                  Я не очень понял, а зачем они Вам?

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

                                  Кроме этого существуют отношения между моделями, я их реализовывал для backbone, но сколько можно=)
                                    0
                                    Один раз :) Нужную Вам фабрику, если такой нет готовой :) У всех своя специфика. Для большого проекта фабрика на сотню строчек кода — это пшик.
                                      0
                                      Лично я не считаю, что модели должны уметь себя сохранять и т. п. — это функция DAL, который должен вызываться из контроллера. Паттерны типа ActiveRecord пускай и удобны, но по сути это антипаттерны, нарушающие SRP. В общем бывает приятно, когда фреймворк позволяет не реализовывать антипаттерны руками, если уж решил их использовать, но он не должен быть под них заточен, чтобы их неиспользование не влекло усложнение кода. Грубо говоря, антипаттерны могут быть библиотекой в составе фреймворка, но не должны быть каркасом фреймворка (тавтология получилась, но так исторически сложилось, что большинство фреймворков по сути являются смесью pure фреймворков (каркасов) и библиотек).
                            0
                            Насколько я понимаю, dirty checking Angular'а позволяет Вам иметь в качестве моделей обычные JavaScript-объекты со свойствами и, возможно, с методами. То есть для реализации берется функция-конструктор, присваиваются свойства, на прототип навешиваются методы.

                            Angular понимает массивы и, по идее, массиво-подобные объекты — то есть Вы можете создать обычный Array, заполнить его своими объектами и отдать Angular'у в качестве модели коллекции.

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

                              Так то это не критично, просто хотелось поставить все точки над i.
                              0
                              Я так понимаю, что model — это объект javascript — его можно перевести в json и сохранить в свойстве localstorage и также целиком или частично загружать
                              0
                              Кому интересно 15 июня будет мастер-класс
                              Ваш первый проект на AngularJS (целый день)
                              devconf.ru/offers/25
                                0
                                В Москве…
                                  0
                                  Меня больше волнует, что дорого :( До Москвы бы доехал, на вокзале бы переночевал :) за свой счет, но почти ползарплаты отдать не могу себе позволить :(
                                    0
                                    Ах, так там еще и за деньги)) Проще самому с докладом выступить
                                0
                                Не рекомендую использовать RequireJS с Ангуляром. Хотя это, конечно, возможно, я не видел ни одного случая, когда применение RequireJS было бы выгодно на практике.

                                Выгода от применения RequireJS заключается в асинхронной загрузке только необходимых файлов, благодаря чему уменьшается время первоначальной загрузки страницы. Так же не нужно следить за очередью загрузки js файлов, что в крупных проектах (с десятками файлов) приводит к постоянным проблемам, приходится поддерживать определенный порядок загрузки.
                                Так же когда вы измените лишь один js файл, то клиент скачает только измененный файл, а остальные возьмет из кэша. В случае же одного объединенного js файла клиенту придется скачивать его снова, что опять приводит к большему времени ожидания загрузки.
                                  0
                                  Так, чтобы понять вас до конца — что в вашем понимании «огромное приложение»?
                                    0
                                    Не увидел ссылки на оригинал статьи :(

                                    UPD: Нашёл, внизу, рядом с именем автора перевода.
                                      0
                                      ссылка процессе сборки angular.js не рабочая

                                      Only users with full accounts can post comments. Log in, please.