Python conf in Kharkiv, Nov 16 with Intel, Elastic engineering leaders. Prices go up 21.10

Асинхронные вызовы в AngularJS

Начал разбираться с AngularJS с целью быстро накидать прототип приложения, что по большому счету и получилось за пару вечеров. Затем решил «сделать правильно» и вынести код из app.js в отдельные модули. Так как контроллеры получились «толстыми», попробовал использовать сервис и... обнаружил, что при использовании $http логика взаимодействия с API не помещается в сервисе — предполагается возвращать promise, и в контроллере обрабатывать результат — что, по-моему, неудобно, особенно при потребности создать «обертку» на серию запросов. Есть ли какие-то решения этой проблемы?

LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Оставлю ссылку тут, чтоб не потерять и просматривать по мере осмысления sauceio.com/...-resource-vs-restangular

посмотрите в сторону RxJS

посмотрите в сторону $resource сервиса вместо $http. Он позволяет например такое:
HTML
<span ng-bind="data"></span>
JS
$scope.data = $resource('/api/data').get();

при этом у $scope.data прототипа будут все методы промиса

потом даже можно будет $scope.data.$save() и post запрос отправился на сервер

Хм, цікаво, раніше використовував лише $http.

Здається, що пропонований вами $resource щось типу ORM-методів в PHP, так?

А как хендлить ошибки при помощи $resources? Есть ли аналог .success/.error callbacks?

Resource предполагает, что «ошибки» хендлятся сервером и возвращаются в виде http кодов, которые перехватывают http interceptors, настратваемые в config фазе. Кроме того, любой resource при определении предполагает указание своих перехватчиков

Спасибо за ответ. Естественно, под ошибками я подразумевал server error reponse (группы 4хх и 5хх).

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

при этом у $scope.data прототипа будут все методы промиса

Для редких, специфичных случаев. Централизованное решение лучше, чем множество $scope.data.message

Что вам мешает по прежнему возвращая промис обрабатывать результат запроса (или даже цепочки запросов) прямо в сервисе? Просто возвращайте свой промис, и сами его контролируйте.

angular.module('myModule').factory('myService', ['$http', function($http) {
    function fetchOne() {
        return new Promise(function(resolve, reject){
            $http.get('/server/call').then(
                function (data) { 
                    // doSomethingWithData; 
                    resolve(data);
                },
                function (error) { 
                    // doSomethingWithError; 
                    reject(error);
                }
           );
        })  
    };
    
    // Several parallel requests
    function fetchOne() {
        return new Promise(function(resolve, reject){
            Promise.all([
                $http.get('/server/call/1'),
                $http.get('/server/call/2'),
                $http.get('/server/call/3'),
                $http.get('/server/call/4'),
                $http.get('/server/call/5')
            ]).then(
                function (data1, data2, data3, data4, data5) { 
                    // doSomethingWithData; 
                    resolve(data1);
                },
                function (error) { 
                    // doSomethingWithError; 
                    reject(error);
                }
           );
        })  
    };

    // Public API
    return {
        fetchOne: fetchOne,
        fetchFive: fetchFive
    };
}]);

В случае с Ангуляром конечно лучше бы использовать встроенный $q, но концепция та же

понял, буду разбираться с resolve/reject

Посмотрите здесь, очень дохочиво разжевано:
habrahabr.ru/post/221111
PS: надеюсь, ссылки на хабр здесь пока еще не запрещены.

то есть, вы предлагаете в сервис, респонсобилити которого закрыть приложение от деталей работы с сервером вбрасывать некий хендлинг ошибок (который обычно повлечет изменения ЮАЙ) ? мягко говоря это както не гуд

Reject всегда вернёт управление назад инициатору — там и меняйте юай. Но раз у топикстартера есть задача предварительно обработать данные, то и ошибки ему тоже вероятно понадобится предварительно обработать. Чтобы передать в контроллер на отрисовку готовыми.
А может и не понадобится, тогда //doSomethingWithError будет nothing

Только еще один промис вокруг другого добавит неясности а пользы ноль. И как я понял ТС то у него под обработкой подразумевается как раз некий юай, но може я его не так понял

С моей ТЗ ещё один промис вокруг другого научит новичка их грокать. А если он не грокает базовую их концепцию то цепочки ему писать просто рано — подводные камни (вроде обработки ошибок в цепочке) затянут модуль на день.

И как я понял ТС то у него под обработкой подразумевается как раз некий юай, но може я его не так понял
обнаружил, что при использовании $http логика взаимодействия с API не помещается в сервисе

и обертывание в новый промис абсолютно не имеет смысла, учите промисы

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

Почему же у вас тогда в коде resolve(data1) а не return data1?

Потому что return не зарезолвит внешний промис.

ммм, на самом деле то что вы предложили с промисами не поможет разобраться, а потому тогда лучше старая, ламповая, добрая колбек функция

предполагается возвращать promise, и в контроллере обрабатывать результат — что, по-моему, неудобно, особенно при потребности создать “обертку” на серию запросов.
Передавайте сервісу scope і вам не прийдеться обробляти дані в контролері.

Ewwww. Вы еще на rootScope в сервисах делайте $watch — и потом говорите что Angular медленый.

Бачу ваш скепсис, не бачу ваших аргументів.

Якщо обробка запитів дуже велика, про що говорить автор теми, то чому б її не винести в сервіс? Про яке сповільнення ви кажете, через що воно буде виникати?

Зачем scope для обработки данных?

Думаю мені не цікаво вести дискусію по AngularJS з людиною, яка не розуміє для чого scope передається в сервіс, при асинхронному запиті.

Ок. Действительно, что я могу знать про Angular...

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

Ну scope, звичайно ж, простіше тримати в контролерах — там не прийдеться навіть робити scope.$apply().

Але якщо при асинхронному запиті є потреба написати багато коду для його обробки, то дотримуючись рекомендації розробників «контролер повинен бути маленьким і читабельним», можна частину коду винести в сервіс.

Хоча можна і не передавати scope в сервіси і при цьому виносити більшу частину коду за межі контролерів, але то вже тонкощі... це теж саме що в PHP поділ коду між контролерами і моделями — не завжди чітко видно що треба залишати в контролерах... особливо при використанні ORM.

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

юзай ngResource, но как по мне промисы намного удобнее и предсказуемы

Я не понимаю как может логика «не помещатся» в сервисе.

stackoverflow.com/...esolved-data-not-promises я бы выбрал первый способ из первого ответа

Подписаться на комментарии