Use response from one $http in another $http in Angularjs - angularjs

First of all I want to use $http in order to receive some data (e.g. students), then I want to make another $http call to get e.g. studentDetails. After that I want to append some part of studentDetails to students JSON.
Also I need response from the first call in order to create the url for the second call.
Problem is that I cannot access response of the first http call inside the another.
Does anybody know how this can be done?
var getStudents = function(){
var deferred = $q.defer();
$http.get("https://some_url")
.success(function(response){
deferred.resolve(response);
}).error(function(errMsg){
deferred.reject(errMsg);
});
return deferred.promise;
}
var appendStudentDetails = function(){
getStudents().then(function(response){
var studentsWithDetails = response;
for(var i=0; i<studentsWithDetails.length; i++){
$http.get("some_url/"+studentWithDetails[i].user.details+"/")
.success(function(res){
//here I want to append the details,
//received from the second http call, to each student
//of the array received from the first http call
//PROBLEM: I cannot access response of the
//first http call inside the another
})
}
})

You're using the deferred anti-pattern as well as the deprecated success/error-callbacks. You should instead use then, since it returns a promise, and you can chain promises.
Here's an example of how you could do it:
function getStudents(){
return $http.get('[someurl]');
}
function appendStudentDetails(studentsWithDetails){
for(var i=0; i<studentsWithDetails.length; i++){
appendSingleStudentDetails(studentsWithDetails[i]);
}
}
function appendSingleStudentDetails(singleStudent){
$http.get("some_url/"+singleStudent.user.details+"/")
.then(function(res){
// Append some stuff
singleStudent.stuff = res.data;
});
}
// Call it like this:
getStudents()
.then(function(response){ return response.data; })
.then(appendStudentDetails);
I decided to structure the appendStudentDetails function a little differently, based on its name, but you could as easily just call getStudents() within the method as you did before.
Beware not to use the i-variable inside your inner then-function, as that would cause you troubles with closure.
Edit: Fixed example to avoid problem with i being under closure.

Related

How do I know that all my $http GET requests are completed?

Using AngularJs 1.6.5 I am making multiple $http GET calls using the for loop. Here is the code:-
for(var i=0; i < 11; i++){
var url = "/api/learner_qa/" + i;
$http.get(url).then(successCallback, errorCallback);
function successCallback(response){
console.log(response);
};
function errorCallback(error){
console.log(error);
};
};
What I want to do is trigger a function when all the GET requests are completed.
I referred to answer posted here and want to know how can this be done on an array as in my case?
The time will likely arise where you need to resolve multiple promises
at once, this is easily achieved through $q.all() by passing in either
an Array or Object of promises which will call .then() once both are
resolved:
You can take an array and push your http calls into it
var array = [];
for(var i=0; i < 11; i++){
var url = "/api/learner_qa/" + i;
array.push($http.get(url))
};
$q.all(array).then(function(response) {
console.log(response)
}).catch(function(error){
console.log(error)
});
Using this code, the response will come once all your requests are successful.
Here is an example documentation

how to use $resource to get the data from local json file

I am trying multiple ways to access my users in a local json file in able to later compare them to the users input. and if there is a match, access is allowed, but my main problem now is just getting to those users.
My code so far:
entire code
json file
What am i doing wrong? i am such a newbie in programming. I have been trying different things and nothing works.
Thanks so much for help
Can you access the file through the browser (via your url localhost:8080/resources/data/users.json)?
If you can't, you will not be able to get access through the $resource or $http.
If you can, any method should work:
1) Via $resource
$scope.users = [];
var UsersResource = $resource('/resources/data/users.json');
where we can get response by callback
UsersResource.get({}, function(response) {
$scope.users = response;
});
or by $promise
UsersResource.get().$promise.then(function(response) {
$scope.users = response;
});
2) Via $http.get
$scope.users = [];
$http.get('/resources/data/users.json').then(function(response) {
$scope.users = response;
});
In your sample, your are trying to get array of users by returning $resource, but $resource returns a object with methods. Each method has callbacks (success, error) or return $promise object.
There is no need to use $resource if you are just going to fetch a json file. Use $http instead:
this.getUsers = function(){
return $http.get('path/to/file.json');
};
And usage:
dataService.getUsers().then(function(resp){
//Do something with the data
$scope.users = resp;
})
$resource is meant to be used when communicating with RESTful apis. What your getUsers() is doing is actually returning a resource-object, upon which you can then call get(). But I recommend using $http in this case.
If you want to use $resouce then you need to create two functions in your controller/factory where "templatesSuccess" return data of request.
getAllTemplates: function(query) {
return $resource(CONST.CONFIG.BASE_URL + 'receiver/get-templates').get(query, obj.templatesSuccess).$promise;
},
templatesSuccess: function(response) {
obj.allTemplates = response;
},

Service which returns multiple promises based on data from single HTTP request

I wish to implement a service which has the following features:
Performs a HTTP request to a given resource only once.
Provides two exported functions, each of which return a promise, where the promise is resolved based on data from the one-time HTTP call.
The two functions shall exist to provide different representations of the fetched data.
The outline of my service so far is as follows:
angular.module('someApp')
.service('someService', function ($http) {
var httpPromise = $http.get('/some/endpoint/').then(
function(response) {
// HTTP response data is processed
});
this.getSomePromise = function() {
// Return a promise which is resolved using one representation of HTTP response
}
this.getAnotherPromise = function() {
// Return a promise which is resolved using another representation of HTTP response
}
});
If there was only the need for one 'getter' function then clearly I could simply have returned the httpPromise.
What is the appropriate way to implement the interface as shown? Is it possible for two or more consumers to call .then() on the same promise, in which case I could merely return httpPromise.then(function(){...modify data...}) from both functions? Or, in this scenario would it be necessary to create a new promise (using $q.defer()) and resolve it somehow based on a cache object which holds the HTTP response?
You can simply create two promises, using chaining, on the http promise:
var httpPromise = $http.get('/some/endpoint/');
var firstPromise = httpPromise.then(function(response) {
return firstTransformation(response.data);
});
var secondPromise = httpPromise.then(function(response) {
return secondTransformation(response.data);
});
this.getSomePromise = function() {
return firstPromise;
}
this.getAnotherPromise = function() {
return secondPromise;
}

rest urls calls parallely angularjs

while I'm getting a json object from Restangular ,another rest url function has been called(before first response comes)
Restangular.all("..").getList("..").then(
function(data){
$scope.dataList = data.dataList;
}, function errorCallback() {
alert("error");
}
);
here before initializing datalist it is calling another function parallely? how can I avoid this?
thanks.
If you need to call your services in specific order then you have two options:
Nesting service callbacks. This solution will prevent execution of the next ajax call until the previous is finished:
Restangular.all("..").getList("..").then(
function(data){
Restangular.secondFunction("..").getList().then(
function (data2) {
// both data and data2 are available
});
}, function errorCallback() {
alert("error");
}
);
Use $q.all() function which waits for the array of deferred objects to finish:
var promises = [];
promises.push(Restangular.all("..").getList(".."));
promises.push(Restangular.secondFunction("..").getList());
$q.all(promises).then(function (results) {
for (var i=0; i<results.length; i++)
{
// all ajax calls have finished now you can iterate through the results
}
});
BTW there is no such thing like parallel execution in javascript.

$http.jsonp not wrapping angular.callbacks

My function
$scope.doCall = function(){
console.log('test');
$http.jsonp('http://api.v2.quran.com/info/surah?callback=JSON_CALLBACK').
success(function(data) {
// this callback will be called asynchronously
// when the response is available
console.log(data[0]);
})
var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=JSON_CALLBACK";
$http.jsonp(url)
.success(function(data){
console.log(data);
});
}
When I look at my network, the second call wraps angular.callbacks._1(OBJECT) while the first just returns [...ARRAY OF OBJECTS...]
The second will output in my console, the first is not doing anything! How can i make it work!
Thats API problem, http://api.v2.quran.com didn't wrap JSON to JSON_CALLBACK, in second case JSON starts with JSON_CALLBACK({... but in first case you get pure JSON, not JSONP. Try to fix it on server.

Resources