How to build an object array by chaining http calls in AngularJS? - javascript

I want to build an array of objects but for each object I need multiple chained http calls. Eg:
var objects = [];
$http.get(/getDataUrl)
.then(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
http.get(objects[i].value1)
.then(function(data){
objects[i].value2 = data.value;
}
}
})
Any ideas how to properly execute this mess?

You will always get 'i' value to be the final index because the renderer will print it when the ajax request gives 200, this will take some time. And in that short time, the for loop would have been executed, therefore you will always get the last index for the value of 'i'
To solve this, you will have to use, closure inside loops
Modify your code like as follows,
var objects = [];
$http.get(/getDataUrl)
.success(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
(function(index) {
var currentURL = objects[i].value1;
$http.get(currentURL)
.success(function(data) {
// both currentURL and i value can be accessed here
console.log(currentURL);
console.log(index); // i value = index
objects[index].value2 = data.value;
});
})(i);
}
})
Now you have access of index inside the anonymous function. Hope this helps

You can try to use success instead of then, as $http isn't a standard promise :
var objects = [];
$http.get('/getDataUrl')
.success(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
}
for(i = 0; i < objects.length; i++)
{
http.get(objects[i].value1)
.success(function(data2){
objects[i].value2 = data2.value;
}
}
})

Try something like that :
Only one loop to rules them all ;)
$http.get(/getDataUrl)
.then(function(data){
for(i = 0; i < data.length; i++)
{
objects[i] = { value1 : data.value }
$http.get(objects[i].value1)
.then(function(data){
objects[i].value2 = data.value;
}
}
})

Related

how to get all values in for loop angular js

when I alert this I only get the last value of id. ican't findout where I'm going wrong
$scope.addToList = function (products,qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx=$scope.order[i].id;
}}};
alert($scope.Thx);
Declare the $scope.Thx as an array first.
$scope.Thx = [];
$scope.addToList = function (products, qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx.push($scope.order[i].id);
}
}
};
This line will overwrite the $scope.Thx for each iteration inside the loop.
$scope.Thx=$scope.order[i].id;
Now there are two ways to get the desired result.
1. If you want the separate alert for each item in the array then:
$scope.addToList = function (products,qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx=$scope.order[i].id;
alert($scope.Thx);
}}};
2. If you want single alert for all the items.
declare $scope.Thx as an array first.
$scope.Thx = [];
$scope.addToList = function (products, qty) {
if ($scope.order.length > 0) {
for (var i = 0; i < $scope.order.length; i++) {
$scope.Thx.push($scope.order[i].id);
}
}
};
var tempVar="";
for(var i=0; i<$scope.Thx.length;i++)
{
tempVar += $scope.Thx[0]+"\n";
}
alert(tempVar);

How to check duplicate entries while adding to javascript object dynamically?

I have this AngularJS service.
demoService.getDemoData($scope.countEP).then(function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
$scope.allEditorPicks.push(data[i]);
}
});
In this case,allEditorPicks is an array i have defined at the top of the code as follows.
$scope.allEditorPicks = [];
Here's the problem, when I'm using this array and printing these data, the array has same items. Duplicating. So I need a way to check existing items and stop adding them in that allEditorPicks array. We need to do this inside the for loop. I tried adding another loop inside the for loop and read the allEditorPicks array and check. But that doesn't work too.
demoService.getDemoData($scope.countEP).then(function (data) {
console.log(data);
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < $scope.allEditorPicks.length; j++) {
if ($scope.allEditorPicks[j].itemName == data[i].itemName) {
console.log("Item Exists")
} else {
$scope.allEditorPicks.push(data[i]);
}
}
}
});
This is the solution I tried. My browser got freezes and stopped working when I run this code. Please give me a solution.
first, sort the array by itemName and then remove the duplicates according to the order.
data = data.sort(function(a,b){
return a.itemName - b.itemName;
});
for (var i = 0; i < data.length; i++) {
if(data[i].itemName === data[i++].itemName){
console.log("Item Exists");
}else {
$scope.allEditorPicks.push(data[i]);
}
}
Try this :
demoService.getDemoData($scope.countEP).then(function (data) {
for(let i = 0; i < data.length; i++){
let found = $scope.allEditorPicks.find(elt => {
return elt.itemName === data[i].itemName;
});
if(!found){
$scope.allEditorPicks.push(data[i]);
}
}
})

javascript array - increment value at given key

I have a dynamic array and I am trying to increment the value by 1 if the key exists in the array. According to my debug it is incrementing the key and and creating a second key/value pair.
A snippet of my code:
for (var i = 0; i < choices.length; i++) {
console.log(choices[i]);
if (choices[i].YearTermId == 1) {
if (!lookup(firstChoice, choices[i].FirstChoiceOptionId)) {
firstChoice.push({
key: choices[i].FirstChoiceOptionId,
value: 1
});
} else {
firstChoice[choices[i].FirstChoiceOptionId] = firstChoice[choices[i].FirstChoiceOptionId] + 1;
}
more if/else..
function lookup( arr, name ) {
for(var i = 0, len = arr.length; i < len; i++) {
if( arr[ i ].key === name )
return true;
}
return false;
}
You're using an array where you should be using an object. If you use an object, your code can be rewritten as:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
var firstChoiceOptionId = choices[i].FirstChoiceOptionId;
if (choices[i].YearTermId == 1) {
firstChoice[firstChoiceOptionId] = firstChoice[firstChoiceOptionId]
? firstChoice[firstChoiceOptionId] + 1
: 1;
/* ... */
}
}
If you need the data as an array afterwards, just map it:
var firstChoiceArray = Object.keys(firstChoice).map(function(key) {
return {
key: key,
value: firstChoice[key]
};
});
Conversely, if you have an input array and want to convert it to an object for manipulation, reduce it:
var firstChoice = firstChoiceArray.reduce(function(result, current) {
result[current.key] = current.value;
return result;
}, {});
I think you should increment value key, like:
firstChoice[choices[i].FirstChoiceOptionId].value ++;
And I would like to rewrite this code to:
var firstChoice = {};
for (var i = 0; i < choices.length; i++) {
if (choices[i].YearTermId == 1) {
if (!firstChoice[choices[i].FirstChoiceOptionId]) {
firstChoice[choices[i].FirstChoiceOptionId] = 0;
}
firstChoice[choices[i].FirstChoiceOptionId]++;
}
}
console.log(firstChoice);
Try with Array.map:
Example:
var a = [{key:"ab","value":1},{key:"cd","value":1},{key:"ef","value":1}];
a.map(function(item){if(item.key == this){item.value++}}, "cd");
So, a[1] will have value 2 after that.

Javascript array not getting modified

I have some JSON data in the "data" variable.
FORMAT :
{
"0" : {"names":"Pooja, Trivedi"},
"1" : {"names":"Pooja, Rooster"}
}
I need to implement a map so as to count the different names:
Pooja = 2
Trivedi = 1
Rooster = 1
Here is the implementation:
map = new Array();
data = jQuery.parseJSON(data); //convert JSON to object
for (var i = 0; i < data.length; i++) {
var names = data[i].names.split(','); //split the CSVs
for (var j = 0; j < names.length; j++) {
if (map[names[j].trim()] === undefined) {
map[names[j].trim()] = 1;
} else {
map[names[j].trim()]++;
}
}
console.log(map); //shows progressively filled arrays
}
console.log(map); //shows [], an empty array
Inside the loop, the map is updated.
However after the end of the i loop, all we have is an empty array.
How is this to be resolved?
First of all, you don't want to use for (var i = 0; i < data.length; i++) to traverse your data object, because a Javascript object doesn't have a length property like an array would. So, use a for (var i in data) instead, to traverse all the keys in the object.
This works:
var data = {
"0" : {"names":"Pooja, Trivedi"},
"1" : {"names":"Pooja, Rooster"}
}
var map = {};
for (var i in data) {
var names = data[i].names.split(',');
for (var j in names) {
var name = names[j].trim();
if (map[name]) {
map[name]++;
} else {
map[name] = 1;
}
}
console.log(map); //shows progressively filled arrays
}
console.log(map); //shows the full array
And you don't want to use an array as your map. You should instead use an object.
I like this version better:
var data = {
"0" : {"names":"Pooja, Trivedi"},
"1" : {"names":"Pooja, Rooster"}
};
var nameCounts = {};
for (var item in data) {
data[item].names.split(", ").forEach(function (name) {
if (name in nameCounts) {
nameCounts[name]++;
} else {
nameCounts[name] = 1;
}
});
}
console.log(nameCounts);

How to rewrite loop to recursion

I implemented a search function and loop that search by collection. In first iteration I need to search by all collection, but all next iterations only by result of the first iteration. I use if-statement if (i >= 1) collection = result; to do it, but it's not safe because I need to save collection. Is it possible to rewrite loop to recursion function? How I can make it or make my code elegant?
var targets = target.split(' '); // => ['hello', 'world'];
for (var i = 0; i < targets.length; ++i) {
if (i >= 1) {
collection = result;
}
result = includes(collection, props, targets[i]);
}
My search function:
function includes(collection, props, target) {
var result = [];
var collection_length = collection.length;
var props_length = props.length;
var target_length = target.length;
for (var i = 0; i < collection_length; ++i) {
for (var j = 0; j < props_length; ++j) {
if (collection[i][props[j]]) {
if (collection[i][props[j]].toLowerCase().slice(0, target_length) === target) {
result.push(collection[i]);
continue;
}
}
}
}
return result.length !== 0 ? result : false;
}
var result = collection;
for (var i = 0; i < targets.length; ++i) {
result = includes(result, props, targets[i]);
}
Maybe I'm missing something but isn't this what you're trying to do?

Categories

Resources