global variable value is lost when exiting function that defines it [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I've written a piece of javascript/jquery that reads a textfile.
I'm having trouble with the variable "fieldname". I declared it in the outer function(), and I assign a value to it in the inner function() that actually reads the file. But right after I leave the inner function, the content of the variable is lost. The code:
<script>
$(document).ready(function(){
var usedlanguage = $("#usedlanguage").html();
var fieldname = new Array();
$.get('Language.txt', function(data)
{
var lines = data.split('\n');
var res="";
for(var i = 0; i<lines.length;i++)
{
var splitup = lines[i].split('\t');
fieldname[i] = splitup[0];
res = res + fieldname[i] + '\n';
}
alert("fieldname length = " + fieldname.length); // here everything is OK
alert("" + res); //this is good.
});
alert("fieldname length = " + fieldname.length); // here it suddenly returns 0.
});
</script>
Is there something wrong with my understanding of scopes? Or is it a problem that there are two function() defined? Or something else?

You need to declare the variable outside DOM ready event to make it global. currently its context remains only in ready event and not beyond that. Use it in this way::
var fieldname = new Array();
$(document).ready(function(){
//rest code
});

Related

Pass reference variable outside the function [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
What is the scope of variables in JavaScript?
(27 answers)
Closed 3 years ago.
In a function to obtain certain data with a json, I want to use this data in a variable and then use it in another function. The problem is that it does not work for me
First of all, obtaining the data with a json and printing it in place on the screen, until now, the problem starts when I save the data in a variable
function cargarPropuestas() {
var peticionLoc = new XMLHttpRequest();
peticionLoc.open('GET', 'https://api.ipdata.co/es?api-key=b3ae31a7a74386088875d7d285250b58778e13de985b2f561910b6bd');
peticionLoc.onload = function () {
var datosLoc = JSON.parse(peticionLoc.responseText);
var elementoLoc = document.createElement('div');
elementoLoc.innerHTML += (datosLoc.city + ', ' + datosLoc.country_name);
loc.appendChild(elementoLoc);
var country = datosLoc.country_name;
}
peticionLoc.send();
What interests me here is the variable COUNTRY
And here the problem begins, since when I "leave" the requestLoc.onload = function () {} I can not call the variable COUNTRY to use it below
What I need is to know how to get the information of this variable out of the function, in order to use that data
You can declare country outside both functions.
var country;
function cargarPropuestas() {
//...
peticionLoc.onload = function () {
//...
country = datosLoc.country_name;
}
peticionLoc.send();
}

Array Is Empty When It Isn't... JavaScript [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
So what I'm doing is getting values from a json file and pushing them to an array so that I can randomly select one and it is displayed in an html file. The problem i'm having is that even though something is in the array, it treats it as if it is empty...
var quotes = [];
var authors = [];
function loadJSON(callback) {
var xobj = new XMLHttpRequest();
xobj.overrideMimeType("application/json");
xobj.open('GET', 'quotes.json', true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
// Required use of an anonymous callback as .open will NOT return a value but simply returns undefined in asynchronous mode
callback(xobj.responseText);
}
};
xobj.send(null);
}
function init() {
loadJSON(function(response) {
// Parse JSON string into object
var data = JSON.parse(response);
for(var i in data){
var key = i;
var val = data[i];
quotes.push(key);
authors.push(val);
}
});
}
init();
var index = Math.floor(Math.random()* (quotes.length + 1));
document.getElementById("p1").innerHTML = "<span class=\"quotes\">“</span>" + quotes[index] + "<span class=\"quotes\">”</span>" + "<span id=\"author\">" + " – " + authors[index] + "</span";
So in my init function it pushes the key and the val to an array but it treats it like it's empty... i'm sorry if this is a simple question but i'm pretty new at JSON. Thanks
I think your problem is that you're executing the last 2 lines of your code (those following the call to init function) before the work within the init actually completes.
In other words, pass a callback to init just like you did to loadJSON, then execute last 2 lines within.
As pointed by Xufox you are dealing with async code, when getElementById runs your request for data has not finished yet, so you end up with an empty array for innerHTML.
This is not related to your question, but void to use for ... in as much as you can when dealing with arrays, prefer old school for for that or, if you are using Babel, for of.

Why is my function not returning the array? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
This is my code:
document.getElementById('revealUser').onclick = displayDaUsers
function displayDaUsers(){
pullAllUsersFromDB();
debugger;
}
function pullAllUsersFromDB(){
rootRef.child('users').on('value', function(snapshot) {
var users_array = [];
var users_object = snapshot.val();
Object.keys(users_object).map(function(key) {
users_array.push(users_object[key]);
});
// window.dateApp.allUsers = users_array;
return users_array
});
}
html:
<input type="submit" id="revealUser" value="reveal user">
I put a debugger in to see the problem but it does not help. When I go into the console and type in users_array
I get Uncaught ReferenceError: users_array is not defined(…)
NEW CODE (EDIT):
according to another stackoverflow answers this should work..
function displayDaUsers(){
var test = pullAllUsersFromDB();
console.log(test);
//pullAllUsersFromDB();
//debugger;
//setUpFirstUser()
}
function pullAllUsersFromDB(){
rootRef.child('users').on('value', function(snapshot) {
var users_array = [];
var users_object = snapshot.val();
Object.keys(users_object).map(function(key) {
users_array.push(users_object[key]);
});
//window.dateApp.allUsers = users_array;
return users_array
});
}
The return value users_array is local to the scope of the anonymous callback function function(snapshot) {.... In other words, its value is lost outside of that scope.
At what point in your logic do you need access to user_array? If you need access to it outside of the context of your functions, maybe it makes sense to define a variable with greater scope, and then setting its value in your anonymous function. E.g.
document.getElementById...
var arr;
...
function pullAllUsersFromDB() {
...
...function(snapshot) {
arr = users_array;
});
}
// pullAllUsersFromDB() (and its callback) must be called for arr to be defined at this point in execution

How does Javascript(NodeJS) handle scope and context with regard to events [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I'm a bit confused in a situation,
given the sample code here where I'm loading several urls, and connected the event Listener:
var pages= Array();
var loading= Array();
for(i=0; i < urls.length; i++){
var page =new WebPage(urls[i]);
page.onLoadStarted = function() {
loading[i]= true;
console.log('Loading started');
};
pages[i]=page;
}
I have 5 urls, and I get 5 times "Loading started" in the console output, however the loading array had only one value defined (true) all the rest are "undefined";
Looks like when the event is triggered loading[i]= true; uses the last value of I to access the array instead of using its address. How can I fix that ?
I've tried adding a property to the page object, but same thing happens;
Here is what I've tried:
var pages= Array();
for(i=0; i < urls.length; i++){
var page =new WebPage(urls[i]);
page.onLoadStarted = function() {
page.loading= true;
console.log('Loading started');
};
pages[i]=page;
}
If onLoadStarted is an event handler then the for loop is executed much faster than the all the event handlers. In that time i is 5 and during each function call, the sixth index of the array is populated with a true value. As the lower indices of array do no have any set value you get such output.
One option is using the Array.prototype.forEach or Array.prototype.map method. Both functions take a function as the handler. The handler which is a function, creates a new scope and remembers the defined values.
urls.forEach(function(url /* element */, i /* index */) {
var page = new WebPage(url);
page.onLoadStarted = function() {
loading[i]= true;
console.log('Loading started');
};
pages[i]=page;
})
Try with this code (es6)
let pages = Array();
urls.map((url,i) =>{
let page = new WebPage(urls[i]);
page.onLoadStarted(() =>{
loading[i] = true;
console.log('Loading started');
})
(es5)
var pages = Array();
urls.map(function(url,i){
var page = new WebPage(urls[i]);
page.onLoadStarted(function(){
loading[i] = true;
console.log('Loading started');
})

Access this in prototype function after a callback [duplicate]

This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 7 years ago.
I have following code :
function A() {
this.value = 'a_value';
}
A.prototype.getValue = function(){
console.log(this.value); // got undefined, expected 'a_value'
}
setTimeout(new A().getValue, 100);
why i get this.value as undefined.?
and how how do i access this.value?
EDIT : i am not allowed to change the setTimeout line (last line) of code.
Hint: have you tried console.log(this);?
You are only passing the getValue function to setTimeout, not its context. Something like this would work: setTimeout(function() {new A().getValue();},100); But without changing that last line, there's basically nothing you can do.
you can avoid using the this altogether and not having this kind of problems with the following technique :
var A = function () { // no new no this
var value = 'a_value';
var getValue = function(){
console.log(value);
};
return Object.freeze({
getValue ,
});
};
setTimeout(A().getValue, 100);
or write
var a = new A();
before, and then
setTimeout(a.getValue.bind(a), 100);

Categories