javascript: not getting proper results with callback function [duplicate] - javascript

This question already has answers here:
Length of a JavaScript object
(43 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I looked at similar questions and tried Object.key(patientList).length but it returns 0. I was recommended to use callbacks and this how I am implementing it.
var data;
var patientList = {};
var parseDate = d3.time.format("%d/%m/%y").parse;
function input_Data() {
d3.json("data.php", function(error, json) {
if (error) return console.warn(error);
data = json;
console.log(data);
for(var i = 0; i < data.length; i++) {
var name = data[i].name;
//data[i].dates = parseDate(data[i].dates);
if(!patientList[name]) {
var newPatient = {
dates: [data[i].dates],
alpha: data[i].alpha,
beta: data[i].beta
};
patientList[name] = newPatient;
} else {
patientList[name].dates.push(data[i].dates);
}
}
console.log(patientList);
console.log(Object.keys(patientList).length);
console.log(Object.keys(patientList));
});
}
function number_of_patients(callback) {
callback();
console.log(patientList);
console.log(Object.keys(patientList).length);
console.log(Object.keys(patientList));
}
number_of_patients(input_Data);
console.log inside the input_Data function displays correct results with length 4. And console.log in the number_of_patients displays correct patientList but 0 length and doesn't display name (keys) either. I have read similar posts but still can't fix the problem here.
Any help would be much appreciated.

In Javascript, generic objects do not have a length property.
Common facts about Javascript objects:
Objects contain key: value pairs where the keys are strings and values may be any type.
Objects do not have a .keys() method to get all of the keys, except...
Ecmascript 5 provides an Object.keys() which can be called explicitly as do some 3rd party libs like underscore.js
initialized using curly braces {} and key:value pairs
Before that, the usual way to count or access all of the keys unique to a specific instance of an object is with a loop like the following:
l=0;
for(var k in obj){
if (obj.hasOwnProperty(k)){
// hasOwnProperty ignores keys from the prototype chain
// do something with key k, value obj[k]
++l;
}
}
// the object has l keys specific to this instance
If you need to quickly get a length you should consider using an array object:
Array objects (x = [1,2,3,'sam',{'name':'fred', 'status': 'dead'}]) have numeric indices starting with 0 and can contain arbitrary type members.
have a length property (x.length is 5)
values are accessed by numeric indices with square brackets, i.e. x[2] is 3
initialized use square brackets [] containing a comma separated list of values
And as others said in comments, asynchronous calls generally return immediately -- and without the data or object you want in scope. To access the data you must execute code in the context where the data is defined, i.e. write code that accesses the asynchronous data/object in a callback function, not the main code.

Related

How to access a particular path/adress inside an object? [duplicate]

This question already has answers here:
access object through dot-syntax string path
(2 answers)
Convert a JavaScript string in dot notation into an object reference
(34 answers)
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 2 years ago.
I am having a problem which I think I might have figured out before how to do it but I can't remember now and can't figure it out.
Let's say we have an object thats a few levels deep, meaning it has as values other objects which also have as some of the values objects and so on.
Now how could I make a function to which I pass the object and and adress inside it and I can access the value at that location inside the function like this:
const getValueAtAdress = (object, 'country.city.rules') => {
return //here I need to return the value at object.country.city.rules.
}
Am I missing something obvious?
I thought I'd mention here for posterity that what helped me was the answer using the reduce which is exactly what I used before but I could not remember:
Example that I am using for my particular problem:
let stateLocation = address.split('.').reduce((acc, cur) => acc[cur], state);
Your code shows a function declaration but you can't declare an argument name in quotes
You can however call a function and pass a string.
In that case, you just need to split the string into an array and then loop over that array, building up a "chained" set of string indexes that can be passed to the object. The String.split() and Array.reduce() methods are the key.
let obj = {
county: {
city: {
rules: "Strict"
}
}
};
const getValueAtAddress = (object, countyCityRules) => {
// Split the string at the dots to form an array...
// The loop over that array and reduce it with an
// accumulator that is then applied to the object.
return countyCityRules.split(".").reduce((acc, cur) => acc[cur], obj);;
}
console.log(getValueAtAddress(obj, "county"));
console.log(getValueAtAddress(obj, "county.city"));
console.log(getValueAtAddress(obj, "county.city.rules"));

JavaScript only logs undefined's that you define? [duplicate]

This question already has answers here:
forEach on array of undefined created by Array constructor
(5 answers)
Closed 5 years ago.
When running this code I expect this to log 5 undefined's. However I only see two. It appears that JavaScript only logs undefined's that you define yourself.
var a = [];
a[0]=undefined;
a[4]=undefined;
a.forEach((i)=>console.log(i))
This logs:
undefined
undefined
Wouldn't you expect it to log 4 undefined's?
Here is a codepen.
Quoting mdn:
forEach method executes the provided callback once for each element present in the array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized (i.e. on sparse arrays like your example),
From what I remember the lo-dash forEach method is different it behaves like you would expect.
It is because of forEach loop.
forEach() executes the provided callback once for each element present in the array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized (i.e. on sparse arrays).
--Source MDN
Example Snippet:
var a = [];
a[0] = undefined;
a[4] = undefined;
a.forEach(function(i) {
console.log(i)
})
for (var i = 0; i < a.length; i++) {
console.log(a[i] + " from for loop");
}
so javascripts arrays are basically just special obejcts that have integer keys (there are some minor differences). so you defined an object with 2 keys values. 0: undefined and 3: undefined. since theres only 2 things in the array, it only prints 2 undefineds.

Counting length of another object property within object function -- JavaScript? [duplicate]

This question already has answers here:
Length of a JavaScript object
(43 answers)
Closed 6 years ago.
I am new to JavaScript objects so please bear with me.
This is my JavaScript:
var dragSources = {
elementSources: {
squareSource: document.getElementById('squareSource'),
circleSource: document.getElementById('circleSource')
},
ifDragSource: function(elem) {
console.log(this.elementSources.length);
}
};
If you look at console.log(this.elementSources.length); you can probably tell that I am trying to get the length of the elementSources property. However, it returns undefined. What am I doing wrong?
It's an object, not an array, therefore it doesn't have a length property.
You could use Object.keys(this.elementSources).length to get the number of keys.
The .keys() method essentially returns an array of the object's keys.
In this case, Object.keys(this.elementSources) returns:
["squareSource", "circleSource"]
Then we are just getting the length of that array, which is 2.
var dragSources = {
elementSources: {
squareSource: document.getElementById('squareSource'),
circleSource: document.getElementById('circleSource')
},
ifDragSource: function(elem) {
console.log(Object.keys(this.elementSources).length);
}
};
dragSources.ifDragSource(); // 2
Technically if you need the length property in a code you have to store the length value directly in the object.
Using Object.key function decreases the code efficiency .
every time you invoke that function to access that value you have to re-run the same function again and again.
in order access to the length property in a js array, the BIG O is always equal to 1.
because when you update the array the length property would be updated consequently
But in that case the big O would be in the size of the Object and (O) = n

How to change the given below json array? [duplicate]

This question already has answers here:
Extract each value of a single property from an array of objects in jQuery
(5 answers)
Closed 9 years ago.
I have a JSON array in the following format:
[{"country":"Algeria"},{"country":"Africa"},{"country":"America"},{"country":"Libiya"}]
I need to change it as follows:
{"Algeria","Africa","America","Libiya"}
How do I do that using Jquery or JavaScript?
In javascript:
var myArray = [{"country":"Algeria"},{"country":"Africa"},{"country":"America"},{"country":"Libiya"}];
var myNewArray = [];
for (var item in myArray) {
var country = myArray[item].country;
myNewArray.push(country);
}
alert(JSON.stringify(myNewArray));
You're actually have the wrong notation in your question. The end result you want should have square brackets ([]), not curly braces({}). Curly braces indicate an object instead of an array but you are not using a key-value structure so the end-result you have above is actually invalid.
Instead it seems you want ["Algeria","Africa",America","Libiya"] as the end-result.
Assuming you mean literally changing the array you have rather than creating a new one and assuming you are using JavaScript:
var arr = [{"country":"Algeria"},{"country":"Africa"},{"country":"America"},{"country":"Libiya"}], // declare your array upfront (but this could be a `JSON.parse()` call)
i = 0, // counter
l = arr.length; // limit/length of array
for (i; i < l; i += 1) {
arr[i] = arr[i].country; // Replace object with value of country property.
}
// `arr` will now be `["Algeria","Africa",America","Libiya"]`
Of course you might want to introduce some checks to ensure that every element of the array has a property called country and some way to deal with that in the rewritten array. But I'll leave you with this for now, see how you get on. This should work if your array is valid to begin with.

How to sort object elements in javascript? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sorting a JavaScript object
Sort JavaScript object by key
I have array:
var arr = {}
arr[2323] = 1
arr[123] = 1
...
arr[n+232323] = 1
How to get all element of aobject sorted by key ( number order ? )
for ( key in arr ) {
alert(typeof(key))
}
return string type.
This is not an assosiative array, this is an object. There are no associative arrays in javascript.
Additionally, objects are not ordered. The order of keys in an object is meaningless.
Assuming there's some reason you don't use an Array in the first place, you can get an Array of the enumerable object properties, and sort that Array...
var sorted = Object.keys(my_obj)
.sort(function(a,b) {
return a - b;
});
This assumes the keys are numeric.
Then you can iterate the Array, and use each key to get the value from my_obj...
sorted.forEach(function(key) {
console.log(my_obj[key]);
});
Short answer: You can't.
Long answer: Associative Arrays in JavaScript are really JavaScript objects. When you add a new element, you're really adding a new member to the object. While most browsers will enumerate those members in the order they were added, the standard states that the order is undefined. You can't sort something that is undefined.
JavaScript objects (maps/dictionaries/associative arrays) have no order, you can't sort them. You will need to convert it to an array first. As you only need the keys of your object in your loop, the Object.keys() function (potentionally needs a shim for older browsers) is destined for the task:
var obj = {...};
var keys = Object.keys(obj).sort(function(a,b){return a-b;}); // numerically sorted
for (var i=0; i<keys.length; i++) {
alert(keys[i]);
// access the values by obj[keys[i]]
}

Categories