Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Сложности с пониманием документации #23

Open
tamtakoe opened this issue May 15, 2013 · 22 comments
Open
Labels

Comments

@tamtakoe
Copy link
Collaborator

Иногда встречаются моменты, которые сложно понять и, соответственно, перевести. Наверное, не стоит по поводу них создавать отдельные темы и пока можно всё собирать здесь.

@tamtakoe
Copy link
Collaborator Author

Первая сложность http://www.angular.ru/api/ngResource.$resource

В общем, все понятно, но тонкости не ясны. К примеру, не ясно что такое «класс» действия. Это тип действия GET, POST, PUT и т.д. или это про внутренний ангуляровский объект действия. Строчка, переведенная как «Методы действий объекта класса или экземпляра объекта могут быть вызваны со следующими параметрами:» громоздка и непонятна. Что хотели сказать в оригинале?

Так же в описании:
ресурс.действие([parameters], [success], [error])
не нашел расшифровки, что, например, success это колбэк, который может возвращать данные. Может быть где-то в другом месте описано?

@maksimr
Copy link
Collaborator

maksimr commented May 16, 2013

Если это про секцию 'Return':

{Object} – A resource "class" object with methods for the default set of resource actions optionally extended with custom actions

то как мне кажется, они хотели сказать что объект resource, когда ты его вызываешь, возвращает объект конструктор класс у которого есть методы get, save, query, remove, delete (по умолчанию).
После того как ты вызываешь у конструктора (User) один из методов который получает данные, например get, он тебе уже возвращает свой экземпляр (экземпляр класса), в их примере это user экземпляр класса User (который в свою очередь является экземпляром resource :) ).

Методы действий объекта класса или экземпляра объекта могут быть вызваны со следующими параметрами:
Методы(действия) класса или его экземпляра могут принимают следующие параметры:

@tamtakoe
Copy link
Collaborator Author

Это они так Active Records описали :-)) Предполагаю, что слово класс взяли в кавычки, потому что в яваскрипте чистых классов нет... А может и вовсе потому, что у нас тут фабрика, а не класс. А конструктор это набор фабричных методов. И судя по всему, объект ресурса и объект ресурсного класса это одно и то же, назвал это ресурсным объектом, а сами данные ресурсом.

Остается разъяснить ситуацию с префиксом $. Что он делает? И почему у них такой странный набор методов по умолчанию. Есть псевдоним для удаления, но нет создания. Или save это создание, а где тогда update? Странная логика.

Перевел весь кусок так:

$resource — это фабрика, создающая ресурсный объект, позволяющий взаимодействовать с RESTful сервером.

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

Возвращает {Object} – ресурсный объект, содержащий действия, которым сопоставлены HTTP-методы. По умолчанию содержит следующие:

{ 'get':    {method:'GET'},
  'save':   {method:'POST'},
  'query':  {method:'GET', isArray:true},
  'remove': {method:'DELETE'},
  'delete': {method:'DELETE'} };

Вызов этих методов вызывает ng.$http с соответствующим HTTP-методом, адресом и параметрами. Когда от сервера приходят данные, создается экземпляр ресурса. Действия save, remove и delete можно использовать так же с префиксом $. Это позволяет легко выполнять CRUD операции (создание, чтение, обновление, удаление) на серверных данных, как показано здесь:

var User = $resource('/user/:userId', {userId:'@id'});
var user = User.get({userId:123}, function() {
  user.abc = true;
  user.$save();
});

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

Методы в действиях ресурсного объекта или его экземпляра могут принимать следующие параметры:

HTTP GET: ресурсный_объект.действие([parameters], [success], [error])
все, кроме GET: ресурсный_объект.действие([parameters], postData, [success], [error])
все, кроме GET: экземпляр_ресурсного_объекта.$действие([parameters], [success], [error])

@tamtakoe
Copy link
Collaborator Author

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

по поводу такой записи:
function forExampleController($scope) { $scope.word="Habrahabra"; $scope.log=""; }
Такие конструкции любят съедать минификаторы (уже набил шишки:)). Лучше писать так:
angular.module('app').controller('SomeCtrl', ['$scope', function ($scope) { ...
или прописывать зависимости через inject:
SomeCtrl.$inject = ['$scope'];

Действительно распространенная проблема? Если так, то стоит написать совет в разделе о записи примеров.

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

Про Resource:

Есть функция resource (настоящее название этой функции ResouceFactory), когда мы её вызываем(передавая необходимы параметры) возвращается
функция-конструктор Resource (модель), которая знает куда и как делать запросы.
У конструктора есть методы(статичные - методы конструктора), с помощью которых можно получить данные с сервера.
Когда мы вызываем один из этих методов (например get),
идет запрос на сервер и после того как сервер ответил
мы передаем данные в наш конструктор Resouce ( new Resource(RESPONSE_VALUE) ),
т.е. создаем экземпляр нашего "класса" Resource.
У экземпляра класса Resource появляются все те же методы как и у класса, только с префиксом $,
которые позволяют экземпляру общаться с сервером. (В действительности методы экземпляра просто вызывают статичные методы класса
используя функцию call: Resource[action].call(this, ...), где this указывает на экземпляр)

Да в JavaScript-е нет понятия класс,
но есть функции конструкторы которые очень похожи по своему поведению.

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

Создание это new Resource(value), так мы в коде создаем экземпляр нужного нам ресурса. Если мы его хотим сохранить мы вызываем метод save.

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

По поводу комментария на хабре:

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

@tamtakoe
Copy link
Collaborator Author

В конструкторе что-то типа такого содержится: var $save = this.save, зачем только префикс вводить непонятно. И любой из этих методов сохраняет-добавляет/удаляет свойства из this. Но все равно получается односторонняя связь: данные на сервере синхронизируются с клиентом, но клиент отследить обновление сервера никак не может, т.к. нет метода $get и чтобы получить что-либо, нужно создать новый экземпляр ресурса. Или я неправильно CRUD понимаю :-)

Тогда лучше переименовать ресурсный объект в конструктор ресурса

Про минификацию. Проглядел, действительно есть. Тогда стоит вынести пожелание все примеры описывать в стиле
angular.module('app').controller('SomeCtrl', ['$scope', function ($scope) { ...
чтобы не учить плохому и люди, тупо скопировав код к себе на сайт, потом бы не сталкивались с этой проблемой.

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

Не мне кажется для примера это не важно, если только пример не про минификацию :)

Зачем пример перегружать не нужной конструкцией, примеры нужны что бы подчеркнуть конкретную особенность которую они описывают. :)

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

В прототипе конструктора Resource содержится:

Resource.prototype['$' + action] = Resource[action];

У экземпляров есть только методы с префиксом '$'.
Сделано это, скорее всего, для того что бы они(методы) не смешивались с данными ($ - подчеркивает что это особые методы, методы экземпляра).

✌️ :)

@tamtakoe
Copy link
Collaborator Author

Да я вот не уверен, сильно ли это перегружает примеры) Сложность почти одна и та же. Более того во всех примерах отдельными функциями только контроллеры записывают. Сервисы, фильтры и т.п. так же через myModule.service/filter/directive. А если пристыковывать контроллер сразу к объявлению метода (а не через переменную), то еще короче получается. Вот и думаю, зачем, вообще, разработчики ввели первую запись :-)

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

Первая запись тебе позволяет не заботится о порядке в котором перечислены зависимости.

// зависит от порядка
angular.module('app').controller('SomeCtrl', ['$scope', '$http', function ($http, $scope) { ... // Wrong!

// не зависит от порядка
function A($scope, $http) { ... }
function B($http,$scope) {...}

@tamtakoe
Copy link
Collaborator Author

Ух... Ну если народ разленится следить за порядком, то потом-то они точно не сообразят. Других преимуществ нет?

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

Такой подход хорош для примеров :)

@tamtakoe
Copy link
Collaborator Author

Ладно, убедил :-) Напишу только о возможных проблемах, чтобы знали когда примеры передирают

@tamtakoe
Copy link
Collaborator Author

Не совсем ясен код:

angular.module('myMod',[]).value('myVal',{}).directive('myDir',['myVal', function(myVal) {...}])

Не мог нигде найти, что это за запись директивы такая .directive('myDir', [ 'myVal', function(myVal) {...}]) Зависимости так что ли подгружаются? Смутно догадываюсь, что value как-то вынимает

@sevaorlov
Copy link
Collaborator

Да, это внедрение зависимости с помощью нотации массива.
А value() используется для внедрения объекта или константы в модуль.
Т.е. переменную myVal теперь можно использовать в директиве и она будет иметь значение пустого объекта в данном случае.

@tamtakoe
Copy link
Collaborator Author

А почему myVal нельзя просто объявить в директиве через var? И что это за зависимость такая от константы? Т.е. получается, что myVal в коде предполагает ссылку на другой модуль?

Пример взял отсюда: https://github.com/angular-ui/ui-sortable/blob/master/src/sortable.js, если что)

@sevaorlov
Copy link
Collaborator

Чтобы сделать глобальную константу, объявить её в одном месте, а использовать в нескольких местах.

@tamtakoe
Copy link
Collaborator Author

А как быть с зависимостями? Странно, что в примере зависимость от глобальной константы, да еще пустой. Какой смысл? Если смысл есть, нужно о нем в документации рассказать, а то сейчас на недокументированную особенность похоже

@maksimr
Copy link
Collaborator

maksimr commented May 17, 2013

В этом и есть основной смысл внедрения зависимостей.
Директива по той ссылке зависит от объекта sortableConfig.
value('sortableConfig',{}) - это заглушка.
Когда кто нибудь будет использовать эту директиву
и захочет ее настроить, ему не надо будет лезть внутрь директивы,
он может просто создать value('srotableConfig', {...}) и при вызове директивы в нее будет передан
уже объект с настройками, а не заглушка.
А директива не будет использовать свободную переменную, тем самым упрощая процесс тестирования
и избавляя себя от излишних знаний окружения.

@tamtakoe
Copy link
Collaborator Author

В этом примере, они без value обходятся, но используют зависимость от директивы анимации https://github.com/angular-ui/bootstrap/blob/master/src/collapse/collapse.js. Но у второго плагина и настроек нет.

Подытожив, смысл value() такой же как у объекта default в jQuery-UI и bootstrap плагинах: Переопределение настроек по умолчанию. Типа, чтобы все попапы на странице всегда слева выползали. Не знаю ни одного случая, когда кто-нибудь эти настройки переопределял, но раз все делают, наверное, такие случаи случаются :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants