JavaScript: preserve a value in a for loop [duplicate] - javascript

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
guys, really need for your helps. I got some code block as follows:
function readyToSubmit(answerPack, answerArr, len) {
for (var i = 0; i < answerArr.length; i++) {
var questionId = answerArr[i].id;
console.log(questionId);
// below is an database async operation
userStore.getDoc(id).then(function(doc) {
// if I console.log 'answerArr[i]' here, it will be undefined
// I know it's 'cause the 'i' here is answerArr.length, so it would be undefined
// I want my questionId differently, but it is always the last one in the array
// I know it's the closure issue, but don't really know how to handle it.
doc.questionId = questionId; // always the same one
answerPack.push(doc);
});
}
}
So, how can I exactly get what I want in every round, I mean different questionId, not always the last one. Many many thanks, :)

You could so somethink like ,
function readyToSubmit(answerPack, answerArr, len) {
for (var i = 0; i < answerArr.length; i++) {
var questionId = answerArr[i].id;
doasynch(questionId);
}
}
function doasynch(questionId) {
userStore.getDoc(id).then(function (doc) {
doc.questionId = questionId;
answerPack.push(doc);
});
}
Read
How Closure works
Closure inside loop issue

Related

JavaScript Why does the index of a for loop add one when adding eventlisteners [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 4 years ago.
I have a question which might sound silly. In the code below there are 2 console.log(i) statements. I want to know why does the second console.log(i) statement returns value of 2 and not 1 as the former on the first iteration (i.e. 1st statement i=n, 2nd: i=n+1). Shouldn't both be equal to 1 until the end of the loop?
function toggleWrapper(){
var el1 = document.querySelectorAll('[class="tCell entryDesc"]');
for (var i = 1; i < el1.length; i++) {
console.log(i);
el1[i].addEventListener('click', function(ev){
console.log(i);
var el2=document.querySelectorAll('[class="additionalInfoContainer"]');
if (el2[i-2].clientHeight) {
el2[i-2].style.maxHeight = 0;
}
else{
el2[i-2].style.maxHeight = el2[i-2].scrollHeight +"px";
}
},
false);
}
}
The problem is that the variable i, within each of your addEventListener() functions, is bound to the same variable outside of the function. simply change your for loop to :
for (let i = 1; i < el1.length; i++)
In the loop with let based index, each iteration through the loop will have a new value of i where each value is scoped inside the loop, so your code would work fine.
i think is something in your code because if you try to make a for loop with two "console.log()" it doesn't do that

How to create functions with dynamic content and store them in an object? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I want to create multiple functions that do different things depending on what's written in a data-table and store them in an object for later use.
Let's look at this simple example:
var arrayPl = [];
function myFunction() {
var carNames = ["Volvo", "Nissan"];
var counter = 0;
for (var i in carNames) {
arrayPl[counter] = function() {
alert(carNames[i]);
};
counter++;
}
}
myFunction();
arrayPl[0]();
Here I wanted to create as many functions as there are car names and save them in an object arrayPl that I could call these functions from later.
Now obviously this example doesn't explain why I would need to do this - but at least it shows my problem, because the first function arrayPl[0](); gives me the second car name instead of the first.
Explaining the reason behind this is too complicated for me now and not that important (Dialogs in Adobe LiveCycle) - I just want to know if what I'm asking is possible in general and if so how.
I prefere this syntax :
var arrayPl = [];
function myFunction() {
var carNames = ["Volvo", "Nissan"];
carNames.forEach( function(element, i) {
arrayPl[i] = function() {
alert(carNames[i]);
}
})
}
myFunction();
arrayPl[0]();

Javascript onclick getvalue is undefined [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
my problem has 2 sides to it.
I am trying to send a simple get value that is generated via a loop like so:
for(var x=0; x<del.length; x++) {
del[x].onclick = function () {
WORK(x);
}
}
Here is my frustrated WORK function
function WORK (x) {
var y = ids[x];
var url = "Delete.php?val=" + y;
window.location = url;
}
I know i just have to pass the value to the function...but if i set it up like that the page executes the function on load and doesn't wait for my click and as is it is now it will always pass an undefined value...what is going on here?
Variable hoisting + non-scoped variables in for loops.
Use .forEach:
Array.prototype.slice.call(del).forEach(function(elem, index) {
elem.onclick = ...
});
Or if you can't, use an immediately-invoked anonymous function:
for (var x = 0; x < del.length; x++) {
(function() {
var elem = del[x];
...
})();
}
When you iterate through the loop, there is only ever one x variable. It is not scoped to the for loop, and changes on each iteration (x++). When you trigger a click, the event handler is called, which in turn calls WORK with the value of x as an argument, which would've already been del.length by the time it runs.

Problems with function callbacks in a for loop [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 6 years ago.
I have a function that runs a for loop and then callback the results of the for loop after it is finished. My issue is that in this for loop function I have 2 functions back to back that have callbacks and they take about half a second for them both to finish (maybe less). When I make the call with proper data, my result array is called back after it is finished, however while the usernames are unique, the pictures are Identical which is not what I want. I believe this has something to do with JS trying to be asynchronous but It just is breaking. Here is my code:
function forCallback(rows, callback){
var done = 0;
for(i = 0 ;i < rows.length; i++){
var steamid = rows[i].steamid;
userinfo.getUserName(steamid, function(name){
userinfo.getUserPicture(steamid, function(picture){
results.push({
name: name,
picture: picture
})
done++;
console.log("Queried " + done + " username(s)")
if(done == (rows.length)){
callback(results);
}
});
});
}
}
The function takes in sql rows and parses the data that way if you were wondering. Any help is appreciated, THANKS so much!!!
The problem is that your asynchronous functions are capturing a reference to steamid and that value changes as the for loop continues. Instead, you need to capture the value of steamid and make sure that value is local to your callback. You can do this using an IIFE.
for (var i = 0; i < rows.length; i++) {
(function(steamid) {
userinfo.getUserName(steamid, function(name) {
...
});
})(rows[i].steamid);
}

How to get the correct value in a for loop in a done() function? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 8 years ago.
I have been trying to find a solution for this, and I've found similar things, but not exactly the same as this problem.
for (var i = 0; i < userArray.length; i++) {
var username = userArray[i];
var employee_id = $('#' + username + '_corresponding_employee_id').val();
followUserBatch(user, username).done(function(data) {
// How to get the correct value of username in here?
outcomes.done.push(username);
})
}
Basically what ends up happening is that when I do outcomes.done.push(username);, username is always the last value of userArray.
You can use an IIFE to scope your variable properly:
for (var i = 0; i < userArray.length; i++) {
var username = userArray[i];
(function (inner_username) {
var employee_id = $('#' + inner_username + '_corresponding_employee_id').val();
followUserBatch(user, inner_username).done(function(data) {
outcomes.done.push(inner_username);
})
})(username);
}
IIFE = Immediately Invoked Function Expression. You can pass-in a variable that will change at a later time, and its value will remain constant within the IIFE.
Here's some explanation of IIFE's: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

Categories