Javascript nested functions variable is not defined [duplicate] - javascript

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
What I am trying to achieve here is to build a chart with the average SLA for each of the 4 regions. For this, I am calling an API to get some ids, I use these ids to call another API and get the SLAs. Then, I'm calculating the average SLA. I have to do this 4 times for each region. In the end, I want to have 2 arrays containing the region names and the average SLAs, so I can build the chart. Problem is, I can't get the SLA data out of these nested functions, so I can build the array. It tells me that the variables are undefined.
So the question is why can't I access the average var as soon as I leave the function? I tried using return average;. I also tried returning from both function(response) and function(data). This is the first JS I write and I feel like there is something very wrong with it. Can you help me find out what?
// This is the fetch that gets me the SLAs and where I calculate the averages.
function regionsla(serviceids, regionName) {
fetch('api.php', {
// request body
}).then(
function(response) {
response.json().then(
function(data) {
var i = 0;
var sum = 0;
var labels = [];
var values = [];
for (const label in data.result) {
sum = sum + data.result[label].sla[0].sla;
i++;
}
average = sum / i;
labels.push(regionName);
values.push(average);
}
)
}
);
}
// This is the main function that runs in the beginning. The fetch is inside a for loop and it will get me the IDs that I need in order to run function regionsla.
async function get_sla() {
regionsids = [58, 59, 60, 61];
americaids = [];
europeids = [];
asiaids = [];
australiaids = [];
for (const regionid of regionsids) {
fetch('api.php', {
// request body
}).then(
function(response) {
response.json().then(
function(data) {
for (const label in data.result) {
switch (regionid) {
case 58:
americaids.push(data.result[label].serviceid);
break;
case 59:
australiaids.push(data.result[label].serviceid);
break;
case 60:
asiaids.push(data.result[label].serviceid);
break;
case 61:
europeids.push(data.result[label].serviceid);
}
}
switch (regionid) {
case 58:
regionsla(americaids, "America");
averageAmerica = average;
console.log(averageAmerica); //this returns
break; // average is not defined
case 59:
regionsla(australiaids, "Australia");
break;
case 60:
regionsla(asiaids, "Asia");
break;
case 61:
regionsla(europeids, "Europe");
}
})
}
);
}
}

The problem is with the scope of variables. Variables will be accessible only within the function they are declared. If you want to access the variable globally, declare it globally. May i know where is the Average variable declared?
As discussed in the comments following code will give you some ideas.
function showName() {
var result;`enter code here`
result = addString('Hello', ' World');
document.write (result );
}
// in below we will check how to return string from function
function addString(fName, lName) {
var val;
val = fName + lName;
return val; // returning string from function
}

Related

Create an array based on my function's result

I'm new to javascript, and scratching my head over this issue:
I used to use the following to grab a bunch of product titles from the page:
CODE 1:
var productTitles = document.querySelectorAll(".product-title");
Then I used the following code to ad a list of these titles to a form's textarea field:
CODE 2:
var MyTextAreaField = document.querySelector("#my-textarea-field");
MyTextAreaField.value = [...productTitles].map(el=>el.textContent).filter(txt=>txt !== 'None').join('\n');
The above worked great, however, I just changed CODE 1 to be a function instead (in order to conditionally return product titles)
The below code is just a rough example of what it looks like:
CODE 3:
var productTitleOne = document.querySelectorAll(".product-title1");
var productTitleTwo = document.querySelectorAll(".product-title2");
var productTitleThree = document.querySelectorAll(".product-title2");
function createProductTitles() {
if (productTypeOne == null) {
return productTitleOne.textContent;
} else if (productTypeTwo == "None") {
return productTitleTwo.textContent;
} else {
return productTitleThree.getAttribute("data-qty") + 'x' + selectionItem.textContent ;
}
}
Problem is, now code 2 no longer works, because it is no longer an Array
So, I tried doing this (adding my function to a variable):
var productTitles = createProductTitles();
But the following still doesn't work, because it's still not really an array
MyTextAreaField.value = [...productTitles].map(el=>el.textContent).filter(txt=>txt !== 'None').join('\n');
So how do I get the result of my function to post to my textarea field?
The problem is the value you're returning on createProductTitles in the Code 1 you're using the array returned by var productTitles = document.querySelectorAll(".product-title"); in the Code 3 you're returning the textContent of that selector, i.e. return productTitleOne.textContent;.
It's important to make a distinction between these two codes because they're sending different data types one is returning an array and the other is returning a string.
So, you need to change your function to return the same the result of the querySelectorAll function
var productTitleOne = document.querySelectorAll(".product-title1");
var productTitleTwo = document.querySelectorAll(".product-title2");
var productTitleThree = document.querySelectorAll(".product-title2");
function createProductTitles() {
if (productTypeOne == null) {
return productTitleOne;
} else if (productTypeTwo == "None") {
return productTitleTwo;
} else {
return productTitleThree
}
}
and then use your function
var productTitles = createProductTitles();
Your function in CODE 3 needs to change.
document.querySelectorAll() returns a NodeList (similar to an array). So it's no good to then try and access the textContent property or call getAttribute() as you do in that function, both of which should instead be called (if desired) on the individual Nodes in the NodeList.
You can modify that function so that the calls you have made take place on the individual Nodes using the spread operator and map function, similarly to how you did in CODE 2:
function createProductTitles() {
if (productTypeOne == null) {
return [ ...productTitleOne].map( productTitles => productTitles.textContent );
} else if (productTypeTwo == "None") {
return [ ...productTitleTwo].map( productTitles => productTitles.textContent );
} else {
return [...productTitleThree].map( productTitles => productTitles.getAttribute("data-qty") + 'x' + selectionItem.textContent );
}
}
This function will return an array of string values that you can do with as you wish, such as:
createProductTitles().filter(txt=>txt !== 'None').join('\n');

Assigning field inside javascript class from ajax [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 4 years ago.
I have code like this:
class Korisnik
{
constructor(korisnikId)
{
this.KORISNIKID = korisnikId;
this.IME = "";
this.UNIQUE_KEY = "";
this.Initialize();
}
Initialize(kid)
{
$.ajax({
type: "POST",
url: "../Php/Korisnik_Get.php",
data: {"korisnikId" : this.KORISNIKID},
success: function(result)
{
var arr = result.split('|');
this.IME = arr[0];
this.UNIQUE_KEY = arr[1];
}
});
}
get naziv()
{
alert("IME: " + this.IME); //Undefined
return this.IME;
}
}
I initialize this class as let myClass = new Korisnik(1);
When I try to get naziv() It returns nothing. I have tested it and when I alert this.IME from inside success code it has value but outside it doesn't. I have read and tried from this question but anything from there is not working for some reason. What to do?
Js getters aren't functions, so you need to access it as myClass.naziv
The other problem you have is that your success function isn't running in the same scope as the rest of your function.
You can use a fat-arrow function to ensure you have the right scope.
success: result =>
{
var arr = result.split('|');
this.IME = arr[0];
this.UNIQUE_KEY = arr[1];
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get

JavaScript returning undefined when it's actually defined [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 4 years ago.
My console.log shows the right values, but I can't access my properties!
var subMenus = [], mainMenu = {};
$.getJSON("js/menu.js", function(data){
var menuJsonish = data.MenuEXTERNAL;
//first turn this into an actual array instead of this dumb, non Json stuff
$.each(menuJsonish, function(e) {
var name = e.valueOf();
var eachMenu = [];
if (e != "MenuSettings") { //skip MenuSettings
$.each(menuJsonish[name], function(element) {
var menuArray = [];
$.each(menuJsonish[name][element], function(item) {
var currentItem = menuJsonish[name][element][item];
var k = currentItem[0].valueOf();;
var v = currentItem[1].valueOf();
if (e == 'Menu1') {
eval("mainMenu."+k+" = '"+v+"'");
} else {
eachMenu[k] = v;
}
});
});
if (e != 'Menu1') {
subMenus[e] = eachMenu;
}
}
});
});
// this one returns undefined...
console.log(mainMenu.Menu1);
// yet this one returns all the correct data as shown in the screenshot
console.log(mainMenu);
I don't understand what is going on here. Shouldn't a value be a value? And more importantly, how do I get my data?
I don't think it's necessary to post the entire "JSON" file (which I did NOT create, but I have to work with), but I will post screenshot #2 which shows what it looks like, and why I have to load it like this.

Javascript: Object properties undefined (very specific case) [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have a function which is a loop by itself and in this loop I am creating an object. But when after the loop I'm trying to access the object properties, I get an response of undefined.
When I try to just console.log the object itself, I get it. The problem is with properties.
I would be grateful, if someone could help me. I did a good research, but didn't manage to find the solution. My case is very strange. Everything is good except the properties. I need the help of senior developers.
Here is the code.
var countMap = {};
var counter = 0;
$('#share_table_body').find('.js-post').each(function () {
var totalCount = 0;
$(this).find('.js-social').each(function () {
var $this = $(this);
var socialType = $(this).data('social-type');
var url = $this.closest('.js-post').data('url');
getShareStatus(url, socialType)
.then(function (shareCount) {
$this.text(shareCount);
if (!countMap[socialType]) {
countMap[socialType] = 0;
}
if (!countMap['total']) {
countMap['total'] = 0;
}
countMap[socialType] += shareCount;
totalCount += shareCount;
countMap['total'] += shareCount;
$this.siblings('.js-total').text(totalCount);
})
.fail(function (err) {
$('.error-notice').removeClass('hidden');
$this.css('color', 'red').text('!');
});
});
counter++;
});
if (counter == $('#share_table_body').find('.js-post').length) {
console.log(countMap);
$('.total-facebook').text(countMap['facebook']);
}
Are you returning anything from your function? Specifically...
return countMap;

Store JSON object in a global accessible array [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I'm trying to build a function that stores an array of JS objects in a global scope (I want to access this from an external Prototype function). However, when I try to return the 'build' array, the array is undefined (this is probally because I need a proper callback function).
How can I achieve this in a proper way?
function getMyJson(url){
var request = $.getJSON(url);
var items = [];
request.done(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
var object = {
name: response[key].name,
id: response[key].id
}
items.push(object);
}
}
});
return items; // This returns 'undefined', probally because the for loop is still running
}
var data = getMyJson('data.json');
console.log(data); // undefined
Thanks in advance
As others have mentioned, callbacks are the way to go.
function getMyJson(url, callback){
var request = $.getJSON(url);
var items = [];
request.done(function(response) {
for (var key in response) {
if (response.hasOwnProperty(key)) {
var object = {
name: response[key].name,
id: response[key].id
}
items.push(object);
}
}
callback(items);
});
}
var data = getMyJson('data.json', function(items){
//items will be defined here.
});

Categories