then(successCallback, errorCallback)
;always(callback)
;$http
- service to perform AJAX requests;$timeout
- AngularJS-wrapper over setTimeout
;$q
- service to create your deferred-objects and promises. var responseData; $http.get('http://api/user').then(function(response){ responseData = response.data; });
var User = function(data){ return angular.extend(this, data); }; $httpBackend.expectGET('http://api/user').respond(200, { result: { data: [{name: 'Artem'}], page: 1, total: 10 } }); var data = {}; $http.get('http://api/user').then(function(response){ var usersInfo = {}; usersInfo.list = _.collect(response.data.result.data, function(u){ return new User(u); }); usersInfo.total = response.data.result.total; return usersInfo; }).then(function(usersInfo){ data.users = usersInfo; });
then
you can build a multi-layered application. ApiWrapper made a request, executed common error handlers, gave the data from the response unchanged to the next layer. There, the data was transformed as necessary and given to the next. Etc.then
will come in success
- callback
following then
. They did not return anything - in the success-callback
will come undefined (see tests).reject
, you need to return $q.reject(value)
. $httpBackend.expectGET('http://api/user').respond(400, {error_code: 11}); var error; $http.get('http://api/user').then( null, function(response){ if (response.data && response.data.error_code == 10){ return { list: [], total: 0 }; } return $q.reject(response.data ? response.data.error_code : null); } ).then( null, function(errorCode){ error = errorCode; } );
$httpBackend.expectGET('http://api/user/10').respond(200, {id: 10, name: 'Artem', group_id: 1}); $httpBackend.expectGET('http://api/group/1').respond(200, {id: 1, name: 'Some group'}); var user; $http.get('http://api/user/10').then(function(response){ user = response.data; return $http.get('http://api/group/' + user.group_id); }).then(function(response){ user.group = response.data; });
$q.all(...)
accepts an array or dictionary of promises, combines them into one that will be resolved when all promises are resolved, or rejected with an error, when at least one promise is rejected. The values will come in success-callback either as an array or as a dictionary, depending on how the all
method was called. $httpBackend.expectGET('http://api/obj1').respond(200, {type: 'obj1'}) var obj1, obj2; var request1 = $http.get('http://api/obj1'); var request2 = $timeout(function(){ return {type: 'obj2'}; }); $q.all([request1, request2]).then(function(values){ obj1 = values[0].data; obj2 = values[1]; }); expect(obj1).toBeUndefined(); expect(obj2).toBeUndefined(); $httpBackend.flush(); expect(obj1).toBeUndefined(); expect(obj2).toBeUndefined(); $timeout.flush(); expect(obj1).toEqual({type: 'obj1'}); expect(obj2).toEqual({type: 'obj2'});
$q.all({ obj1: $http.get('http://api/obj1'), obj2: $timeout(function(){ return {type: 'obj2'}; }) }).then(function(values){ obj1 = values.obj1.data; obj2 = values.obj2; });
spyOn(UserApi, 'get').andReturn($q.when({id: 1, name: 'Artem'})); var res; UserApi.get(1).then(function(user){ res = user; }); $rootScope.$digest(); expect(res).toEqual({id: 1, name: 'Artem'});
$digest
loop must be executed.deferred
objects$q
-service also allows you to wrap any asynchronous operation in your deferred-object with the corresponding promise-object. var postFile = function(name, file) { var deferred = $q.defer(); var form = new FormData(); form.append('file', file); var xhr = new XMLHttpRequest(); xhr.open('POST', apiUrl + name, true); xhr.onload = function(e) { if (e.target.status == 200) { deferred.resolve(); } else { deferred.reject(e.target.status); } if (!$rootScope.$$phase) $rootScope.$apply(); }; xhr.send(form); return deferred.promise; };
var deferred = $q.defer()
deferred.resolve()
reject
in case of error: deferred.reject(e.target.status)
return deferred.promise
$rootScope.resPromise = $timeout(function(){ return 10; }); var res = $rootScope.$eval('resPromise + 2'); expect(res).toBe(2); $timeout.flush(); res = $rootScope.$eval('resPromise + 2'); expect(res).toBe(12);
watch
, then exactly the resolved value will come as a value. var res; $rootScope.resPromise = $timeout(function(){ return 10; }); $rootScope.$watch('resPromise', function(newVal){ res = newVal; }); expect(res).toBeUndefined(); $timeout.flush(); expect(res).toBe(10);
$rootScope.resPromise = function(){ return $timeout(function(){ return 10; }); }; var res = $rootScope.$eval('resPromise()'); expect(typeof res.then).toBe('function');
catch(errorCallback)
as a shortened synonym for promise.then(null, errorCallback)
;always(callback)
renamed finally(callback)
;promise.then
looks like then(successCallback, errorCallback, progressCallback)
, while deferred
has a notify(progress)
method.Source: https://habr.com/ru/post/189084/
All Articles