Using $http after previous $http done - javascript

I have 3 JSON web services which I should use in my application,
I use $http to load from URL, my code is :
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
});
$http.get('http://{url}/news')
.then(function (result) {
storeNews(result);
});
$http.get('http://{url}/pages')
.then(function (result) {
storePages(result);
});
var users = getUsers();
Problems :
1- all $http run together not wait until the previuse $http done.
2- var users = getUsers(); will run before $http done.
UPDATE :
I changed my code to :
var loadedService = {
users: false,
news: false,
pages: false
};
function getUsers() {
deferred = $q.defer();
$http.get('http://{url}/users')
.then(function (result) {
loadedService.users = result;
deferred.resolve('I got users');
console.log("Get users");
});
return deferred.promise;
}
function getNews() {
deferred = $q.defer();
$http.get('http://{url}/news')
.then(function (result) {
loadedService.news = result;
deferred.resolve('I got news');
console.log("Get news");
});
return deferred.promise;
}
function getPages() {
deferred = $q.defer();
$http.get('http://{url}/pages')
.then(function (result) {
loadedService.pages = result;
deferred.resolve('I got pages');
console.log("Get pages");
});
return deferred.promise;
}
getNews().then(getUsers()).then(getPages()).then(function () {
console.log('Done !');
});
When I run my program, I will see :
XHR finished loading: GET "http://{url}/pages". ionic.bundle.js:16185
Get pages sync.js:133
XHR finished loading: GET "http://{url}/users". ionic.bundle.js:16185
Get users sync.js:56
XHR finished loading: GET "http://{url}/news". ionic.bundle.js:16185
Get news sync.js:107
as you can see, first of all pages service loaded, then users service and then news, while in my code I said getNews().then(getUsers()).then(getPages()).
and finally console.log('Done !'); don't show !

You can use one of the ways MajoB or Muhammad suggested or you can have 3 functions that return promise and chain them in the order that you want.
function getUsers(){
deferred = $q.defer()
$http.get('http://{url}/users')
.success(function (result) {
storeUsers(result);
deferred.resolve('I got users')
}).error(function(data, status, headers, config) {
// called if an error occurs
console.log('error');
deferred.reject(status)
});
return deferred.promise
}
function getNews(){
deferred = $q.defer()
$http.get('http://{url}/news')
.success(function (result) {
storeUsers(result);
deferred.resolve('I got news')
}).error(function(data, status, headers, config) {
// called if an error occurs
console.log('error');
deferred.reject(status)
});
return deferred.promise
}
function getPages(){
deferred = $q.defer()
$http.get('http://{url}/pages')
.success(function (result) {
storePages(result);
deferred.resolve('I got pages')
}).error(function(data, status, headers, config) {
// called if an error occurs
console.log('error');
deferred.reject(status)
});;
return deferred.promise
}
For example lets say that you want to get the Pages after you get the News:
getNews().then(getPages())
Each even better to reject a promise on an error case and have an error handling on the chaining:
getNews().then(function() {
console.log('Success');
getPages();
}, function() {
console.log('Failed');
}, function() {
console.log('Executing... ');
});
Ofcourse the chain also returns a promise which you can handle.

you can chain your requests:
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
$http.get('http://{url}/news')
.then(function (newsResult) {
storeNews(newsResult);
$http.get('http://{url}/pages')
.then(function (pagesResult) {
storePages(pagesResult);
});
});
});

You can make $http requests run after each other by putting the code inside the success promise.
var users; // declare `users` variable
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
// second ajax request
$http.get('http://{url}/news')
.then(function (result) {
storeNews(result);
// third ajax request goes here
// .....
// set the value for users
users = getUsers();
});
});

here a little testScript for using promises with angularJs
$scope.myXhr = function(){
var deferred = $q.defer();
$http({
url: 'ajax.php',
method: "POST",
data:postData,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
//if request is successful
.success(function(data,status,headers,config){
//resolve the promise
deferred.resolve("request successful");
})
//if request is not successful
.error(function(data,status,headers,config){
//reject the promise
deferred.reject("ERROR");
});
//return the promise
return deferred.promise;
}
$scope.callXhrAsynchronous = function(){
var myPromise = $scope.myXhr();
// wait until the promise return resolve or eject
//"then" has 2 functions (resolveFunction, rejectFunction)
myPromise.then(function(resolve){
alert(resolve);
}, function(reject){
alert(reject)
});
}

You can try this:
NoticeService.observeReqUser().then(null,null,function(){
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
NoticeService.notifyStatusOne()
});
});
NoticeService.observeReqOne().then(null,null,function(){
$http.get('http://{url}/news')
.then(function (result) {
storeNews(result);
NoticeService.notifyStatusTwo()
});
});
NoticeService.observeReqTwo().then(null,null,function(){
$http.get('http://{url}/pages')
.then(function (result) {
storePages(result);
});
});
var users = getUsers();
You need to create a service to notify the request is done so the next one can be called
app.service('NoticeService',['$q',function($q){
var noticegetUserIsDone = $q.defer();
this.observeReqUser = function() { return noticegetUserIsDone.promise; };
this.notifyStatusUser = function() { noticegetUserIsDone.notify(); };
var noticeReqOneIsDone = $q.defer();
this.observeReqOne = function() { return noticegetUserIsDone.promise; };
this.notifyStatusOne = function() { noticegetUserIsDone.notify(); };
var noticeReqTwoIsDone = $q.defer();
this.observeReqTwo = function() { return noticegetUserIsDone.promise; };
this.notifyStatusTwo = function() { noticegetUserIsDone.notify(); };
};
You will need to call the NoticeService.notifyStatusUser from the end of getUser function so the chain will start to execute (Don't forget to add reference of the NoticeService where you call it)

You can use something like this, if I understand your question correctly:
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
return $http.get('http://{url}/news');
})
.then(function (result) {
storeNews(result);
return $http.get('http://{url}/pages');
})
.then(function (result) {
storePages(result);
users = getUsers();
});
$http.get will return promise.
Updated:
Or more clean solution:
var deferred = $q.defer(),
users;
$http.get('http://{url}/users')
.then(function (result) {
storeUsers(result);
return $http.get('http://{url}/news');
})
.then(function (result) {
storeNews(result);
return $http.get('http://{url}/pages');
})
.then(function (result) {
storePages(result);
deferred.resolve(result);
});
deferred.promise.then(function() {
users = getUsers();
});
Update2:
or more simple:
var request1 = $http.get('http://{url}/users'),
request2 = $http.get('http://{url}/news'),
request3 = $http.get('http://{url}/pages');
$q.all([request1, request2, request3]).then(function(result) {
storeUsers(result[0]);
storeNews(result[1]);
storePages(result[2]);
users = getUsers();
}
But you also need to handle rejection case.

Related

.getAll(...).then is not a function

I updated Angular to version 1.6.4.
So I had to update .success and .error to .then
Now I get the following error:
TypeError: .getAll(...).then is not a function
The Problem is here in the service:
function getAll(page, size) {
return $http.get(baseUrl + '/jobprofiles?page='+page+'&size='+size, {timeout: 5000}).then(function (response) {
data = response;
}), (function(response) {
alertService.setAlert({'message': 'jobmatch.server.unavailable', 'classified': 'danger', 'lives':1});
});
}
Here is the controller:
if($cookies.get("authenticated")=='true'){
//get a list of all candidateprofiles with the use of a page and a size
candidateprofilesService.getAll($scope.page, $scope.size).then(function() {
$scope.data = candidateprofilesService.getData()._embedded.candidateprofiles;
candidateprofilesService.getAll($scope.page, $scope.size+10).then(function() {
if(candidateprofilesService.getData()._embedded.candidateprofiles.length > $scope.data.length){
$scope.moreData = true;
}
else {
$scope.moreData = false;
}
})
});
}
You service code should be like :
myApp.service('candidateprofilesService', function($http) {
this.getAll = function (page, size) {
// just return the promise , don't evaluate here
return $http.get(baseUrl + '/jobprofiles?page='+page+'&size='+size, {timeout: 5000});
}
this.getData = function(){
// your getData() method body, also just return the promise.
}
});
Then in your controller after injecting service,
candidateprofilesService.getAll($scope.page, $scope.size).then(function(response){
//Evaluate promise here and handle the response
}, function(error){
//handle error
});
Your function should be like this,
function getAll(page, size) {
return $http.get(baseUrl + '/jobprofiles?page='+page+'&size='+size, {timeout: 5000}).then(function (response) {
return data = response;
}, function(response) {
alertService.setAlert({'message': 'jobmatch.server.unavailable', 'classified': 'danger', 'lives':1});
});
}

$q doesn't work asynchronously

I am using promise and $q to make an asynchronous call. But it doesn't work.
eventData.js
angular.module('eventsApp').factory('eventData' , function($http ,$q, $log) {
return {
getEvent : function() {
var deferred = $q.defer()
$http({method: 'GET', url: 'http://localhost:8080/springhibernateangularjs/service/events'}).
then(
function(response){
deferred.resolve(response.data);
console.log("succccccc");
},
function(error){
console.log("faiiiiiiil");
deferred.reject(status);
});
return deferred.promise ;
}
};
});
EventContrller.js
$scope.event = eventData.getEvent();
But $scope.event is not loading correctly!
This is how you get the data since you are returning a promise not the results:
eventData.getEvets().then(function(result){
$scope.event = result;
})
There is no need to manufacture a promise with $q.defer as the $http service already returns a promise.
app.factory('eventData' , function($http) {
return {
getEvent : function() {
//RETURN http promise
return $http.get('http://localhost:8080/springhibernateangularjs/service/events').
then(function(response){
console.log("succccccc");
//return to chain data
return response.data;
},
function(error){
console.log("faiiiiiiil");
//throw to chain rejection
throw error;
});
}
};
});
In the controller:
eventData.getEvent().then(function(data){
$scope.event = data;
});

Use output from services to controllers

I want to result of my $http.get from my service to my controller.
myserviceSample.js
function messagesService($q,$http){
var messages;
$http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
messages = response.data;
console.log(messages);
},function error(response){
console.log('error'+ response);
});
console.log(messages);
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
})();
mycontrollerSample.js
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
})();
The above code results gives undefined output.
What i miss?
$q.when object does expect promise/object to make it working. In your case you have to pass promise object to $q.when as you are doing $http.get call. Here messages object doesn't hold promise of $http.get, so you could change the implementation of method like below.
Service
function messagesService($q,$http){
var messages = $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
return response.data;
},function error(response){
return $q.reject('Error Occured.');
});
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
Then controller will resolve that promise & .then will do the trick
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
Note: Using $q to create a custom promise, is considered as bad pattern when you have $http.get method there(which does return
promise itself)
Improved Implementation
function messagesService($q, $http) {
var messages, getList = function() {
return $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response) {
messages = response.data
return response.data;
}, function error(response) {
return $q.reject('Error Occured.');
});
};
return {
loadAllItems: function() {
if (!data)
return getList(); //return promise
else
return $q.resolve(messages); //return data
}
};
};

How to returning data from a resource using angular

I'm creating service layers to interact with Rest server, but I've got some problems with ngResource promises.
var grupogestion= angular.module('app.grupogestion.services', ['ngResource']);
grupogestion.factory('Grupogestion', ['$resource', function ($resource){
return $resource('api/grupogestiones/:action/:id.:format',
{
action: '#action', id:'#id', format:'json'
},
{
'get': {method:'GET'},
'post': {method:'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}},
'save': {method: 'POST',headers : {'Content-Type': 'application/x-www-form-urlencoded'}}
}
);
}]);
grupogestion.service('GrupogestionService',['Grupogestion', function (Grupogestion){
this.findAll = function (){
Grupogestion.get({action: 'index'},function (data, status, headers, config){
return data;
});
}
this.save = function (grupogestion){
Grupogestion.save({'action':'add'},$.param(grupogestion)).$promise.then(
function(data){
alert('k');
return data;
},
function(error){
alert('j');
return error;
}
);
}
}]);
When I call var response = GrupogestionService.save(data) from angular controller, I don't get the data at the same time I call the function, so the question is: How can I modify GrupogestionService for returning data to the controller?
I've tried to return the promise but I couldn't do it. Thanks for helping.
// service code
grupogestion.service('GrupogestionService', ['Grupogestion', function (Grupogestion) {
this.findAll = function () {
Grupogestion.get({action: 'index'}, function (data, status, headers, config) {
return data;
});
};
this.save = function (grupogestion) {
return Grupogestion.save({'action': 'add'}, $.param(grupogestion));
}
}]);
//run in your controller
var response = GrupogestionService.save(data).$promise.then(
function (data) {
alert('k');
return data;
},
function (error) {
alert('j');
return error;
}
);

Returning promise inside async function

I have an AngularJS service method that should return a promise. Within that method is an async call which proceed to do an $http call on success. I am not quite getting the syntax right to return this correctly.
// This function should return a promise
function doFacebook() {
var deferred = $q.defer();
Facebook.login(function(response) {
var p = $http({
method: 'POST',
url: '/auth/facebook',
data: {
token: response.authResponse.accessToken
}
});
p.then(function(data) {
startSession(data);
return data;
}, function(data) {
return $q.reject(data);
});
});
return deferred.promise;
}
I am wanting to return p - not sure how to either attach/replace deferred with it.
You could just resolve deferred object with the promise p returned by the http call inside the facebook login callback. it should resolve/reject the passed-in promise automatically.
function doFacebook() {
var deferred = $q.defer();
Facebook.login(function(response) {
var p = $http({
method: 'POST',
url: '/auth/facebook',
data: {
token: response.authResponse.accessToken
}
}).then(function(data) {
startSession(data);
return data;
}, function(data) {
return $q.reject(data);
});
//Here
deferred.resolve(p);
});
return deferred.promise;
}
A sample demo:-
///BAD CODE ALERT!!
angular.module('app', []).controller('ctrl', function($scope, $q, $http, $timeout) {
function doAsync() {
var deferred = $q.defer();
//Simulating non angular async
setTimeout(function() {
//Simulating http call. $timeout also returns a promise, so.
var p = $timeout(function() {
//uncomment to test reject scenario
if ($scope.reject) {
$scope.reject = false;
throw Error("OOPS i got rejected");
}
return 'Hello, i got resolved!!'
}).then(function(data) {
return data;
}, function(data) {
return $q.reject(data.message);
});
//Here
deferred.resolve(p);
});
return deferred.promise;
}
$scope.runTest = function() {
doAsync().then(function(data) {
$scope.data = data;
}).catch(function(error) {
$scope.data = error;
});
}
$scope.rejectTest = function() {
$scope.reject = true;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<button ng-click="rejectTest()">Reject and then</button>
<button ng-click="runTest()">Run Test</button>
<div>{{data}}</div>
</div>

Categories

Resources