AngularJS multiple $http calls, with multiple results - javascript

I have a LIST of Id's and I want all of them to contact my API.
The way I did it is like this:
var someFunct = function() {
for (var i = 0; i < Apples.length; i++) {
var Apple = Apples[i];
$http.get("APIUrl" + Apple.Id).
success(function (response) {
for (var i = 0; i < response.Appleseeds.length; i++) {
if(Apple.Appleseeds.Id == response.Appleseeds.Id)
{
Apple.Size = response.Appleseeds.Size;
}
}
})
}
So the problem is that Apple[2] has changed value, where Apple[0] and Apple[1] stay untouched. response.Appleseeds have their own list of Id's. So I need to change the Size of ALL THE APPLES not just Apple[2].

You're close, use a closure instead:
var someFunct = function () {
for (var i = 0; i < Apples.length; i++) {
(function (Apple) {
$http.get("APIUrl" + Apple.Id)
.success(function (response) {
for (var i = 0; i < response.Appleseeds.length; i++) {
if (Apple.Appleseeds.Id == response.Appleseeds.Id) {
Apple.Size = response.Appleseeds.Size;
}
}
});
})(Apples[i]);
}
};
Because http doesn't happen instantly, by the time the last success has happened in your code apple has been changed. By wrapping it in a closure you make it so that each call has it's own private Apple.

var deferred = $q.defer();
var someFunct = function() {
for (var i = 0; i < Apples.length; i++) {
$http.get("APIUrl" + Apples[i].Id).
success(function (response) {
deferred.resolve(response)
})
return deferred.promise;
}
}
someFunct().then(function(d)){
// write your code here
}

Related

Problem with showing the results in my Calculator app with this.id

im having trouble using this.id as it doesnt return any value.
https://jsfiddle.net/o432v0L5/
I'm at the point where I want the number to be shown when I press it but it just doesnt work.
for (var i = 0; i < operator.length; i++) {
operator[i].addEventListener('click', function (e) {
alert(this.id)
})
}
var number = document.getElementsByClassName('number')
for (var i = 0; i < number.length; i++) {
number[i].addEventListener('click', function () {
var output = getOutput()
if (output != NaN) {
output = output + this.id;
printOutput(output)
}
})
}```
Have you tried
for (var i = 0; i < operator.length; i++) {
operator[i].addEventListener('click', function (e) {
alert(this.innerText);
})
}

$.when apply for single request

I am trying to use $.when apply in my code. However, it seems that the format return is different for single and multiple request. How can i cater for it?? I am trying not to have another if else outside of it.
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
This is what i do not want to do.
if (apiRequestList.length === 1) {
$.ajax({
});
} else {
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
}
You can simply convert arguments into an array, when the length of apiRequestList is 1:
$.when.apply(null, apiRequestList).then(function() {
var _arguments = Array.prototype.slice.call(arguments);
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
});
Live Example on jsFiddle (since we can't do ajax on Stack Snippets):
function x(a) {
return $.post("/echo/html/", {
html: "a = " + a,
delay: Math.random()
});
}
function doIt(apiRequestList) {
$.when.apply(null, apiRequestList).then(function() {
var _arguments = arguments;
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
console.log("----");
});
}
doIt([x(1), x(2), x(3)]);
doIt([x(4)]);
Example output (it'll vary because of the Math.random()):
a = 4
----
a = 1
a = 2
a = 3
----

React native trouble calling function within another function?

in my React-native app I am trying to call another function within my listenForItems function, but keep getting the error this.populateArray is not a function. In 'this.populateArray(solutions)', this.populateArray is undefined. I do this in other classes and it's working, but for some reason it's not working here. Is there anything I'm missing?
populateArray: function(solutions) {
var completed = [];
var inProgress;
for (var i = 0; i < solutions.length; i++ ) {
if (solutions[i].completed == 0) {
inProgress = solutions[i].id;
}
else {
completed.push(solutions[i].id);
}
}
},
listenForItems: function(cluesRef) {
var solutions = [];
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', function(snap){
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
this.populateArray(solutions);
});
},
The classic this scope issue of javascript. Google will help with better understanding. In short, the word "this" inside a function refers to that function. In this example it refers the anonymous function (callback) that you use in userSolutionsRef.orderByChild. There are many ways to solve this. You can use ES6(ES2015) arrow functions in which case it becomes something like
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', (snap) => {
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
this.populateArray(solutions);
});
or es5 solution
var that = this;
userSolutionsRef.orderByChild('user_id').startAt(0).endAt(0).once('value', function(snap){
var solution = snap.val();
for (var i = 0; i < solution.length; i++) {
if (solution[0].hunt_id == 0) {
solutions.push(solution[0]);
}
}
that.populateArray(solutions);
});

AngularJS: $http response too slow

I am using this code:
$http.get('/api/users').
success(function(data) {
$scope.authors = data;
}).
error(function() {
console.log('API error - config.')
});
And somewhere below (much bellow):
for (var i = 0; i < $scope.authors.length; i++) {
...
};
Sometimes it happens that $scope.authors are not avaliable yet. Is there any way to solve this?
UPDATE
This is the whole block structure:
// author
$http.get('/api/users').
success(function(data) {
$scope.authors = data;
processAuthors();
}).
error(function() {
console.log('API error - config.')
});
// if updating form
$scope.$on('$routeChangeSuccess', function() {
if($routeParams.id) {
$http.get('/api/offers/' + $routeParams.id).
success(function(data) {
// author
function processAuthors() {
for (var i = 0; i < $scope.authors.length; i++) {
if($scope.authors[i].email == data.author.email) {
$scope.author = $scope.authors[i];
};
};
}
Put the loop in the succes part:
$http.get('/api/users').
success(function(data) {
$scope.authors = data;
for (var i = 0; i < $scope.authors.length; i++) {
...
};
}).
error(function() {
console.log('API error - config.')
});
Yes, it doesn't matter how much below it is - you still need to call it from inside the callback because it's an async call:
function processAuthors() {
for (var i = 0; i < $scope.authors.length; i++) {
...
};
}
And then:
$http.get('/api/users').
success(function(data) {
$scope.authors = data;
processAuthors();
})
I used a function to make it look cleaner, but you can copy your code that depends on the callback inside it.
UPDATE
function processAuthors(data) {
for (var i = 0; i < $scope.authors.length; i++) {
if($scope.authors[i].email == data.author.email) {
$scope.author = $scope.authors[i];
};
};
}
$scope.$on('$routeChangeSuccess', function() {
if($routeParams.id) {
$http.get('/api/offers/' + $routeParams.id).
success(function(data) {
// author
processAuthors(data); // just call it here, define it outside

returning a value after for loops

So, I have been trying for the past few hours to get an result out of a function after performing some for loops :
Cluster.prototype.initiate_api_data_fetching = function(username) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function(data_object){
var json_obj = JSON.parse(data_object);
for(var obj_key in json_obj) {
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function(data_obj){
var json_object = JSON.parse(data_obj);
for(var data_key in json_object) {
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
};
};
log(object);
});
};
};
});
};
Making abstraction of all the variables and other things that make no sense to you readers, I would just like to know how can I return the object array with the data that I\m pushing in it. Everything is fine if I\m logging where the /*log(object);*/ is, but if I want to see what the object contains at the end of the function, I get an empty array.
I suggest you add a callback to your main function and call it when done..
Cluster.prototype.initiate_api_data_fetching = function (username, callback) {
var self = this,
object = [];
return self.initiate_available_market_search(username, function (data_object) {
var json_obj = JSON.parse(data_object)
, counter = 0;
function done() {
counter -= 1;
if (counter === 0) {
callback(object);
}
}
for (var obj_key in json_obj) {
if (!json_obj.hasOwnProperty(obj_key)) { continue; }
for (var i = json_obj[obj_key].length - 1; i >= 0; i--) {
counter += 1;
self.initiate_market_items_data_fetching(username, json_obj[obj_key][i].site, function (data_obj) {
var json_object = JSON.parse(data_obj);
for (var data_key in json_object) {
if (!json_object.hasOwnProperty(data_key)) { continue; }
for (var j = json_object[data_key].length - 1; j >= 0; j--) {
object.push(json_object[data_key][j]);
/*log(object);*/
}
}
done();
});
}
}
});
};
PS. 1 assumption is that initiate_api_data_fetching is async.
PS. 2 Follow the advice from the commenters above to improve your code. I answered your immediate question by showing you how to synchronise async calls, but don't stop there.

Categories

Resources