1

I'm trying to get the profile details of some users from my database through their usernames.

for (var i = 0; i < this.all_data.length; i++) {
    this.moduleGetUserProfileByUserName({
      username: this.all_data[i].userCreated
    }).then(data => {
      this.user_data = data.data;
      console.log(this.user_data);
    });
}

But I need to add the data that I am getting, to the same object the username came from, like this.all_data[i].UserData = this.user_data; but I cannot do this inside then because [i] is undefined, and I can't do it outside of moduleGetUserProfileByUserName because then it gets executed before user_data has any data.

What's the correct way to go about this?

my all_data array

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
asdasd
  • 19
  • 3
  • What does your method for getting profile is returning? Can you please add that method also. – Minal Shah Jul 21 '20 at 13:14
  • Could you add "console.log(this.all_data)" before "for" section and see what is printed on the console? – AntiqTech Jul 21 '20 at 13:14
  • @MinalShah my method for getting profile is returning correctly the profile details of each user found in `all_data`. I just need to get this data and put it inside `all_data` so that I can use it from there. @AntiqTech `all_data` before "for" returns some arrays, where each array has data that i need, and a `username` which I am using to get the details. I'll update the post with the data from it. – asdasd Jul 21 '20 at 13:24
  • Does this answer your question? [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – 3limin4t0r Jul 21 '20 at 14:02

2 Answers2

1

Assuming the rest of the code is ok and that your only issue is to have the correct reference to the object index after each async operation, you can proceed as follows:

for (let i = 0; i < this.all_data.length; i++) {
    const currentIndex = i;
    this.moduleGetUserProfileByUserName({
        username: this.all_data[i].userCreated
    }).then((data) => {
        this.all_data[currentIndex].UserData = data.data;
    });
}

i will be constantly updated and at the end of the loop its value will be equal to this.all_data.length, but as const declarations are block scoped, each callback passed to the .then() method will preserve the correct index reference.

Note: I don't know exactly where you want to store the data, but you can use currentIndex as you prefer.

IMPORTANT EDIT: As @3limin4t0r pointed out in the comments, creating currentIndex constant is unnecessary. Interestingly, variables declared using let at for loop initialization time will already be block scoped for each loop cycle.

Ernesto Stifano
  • 3,027
  • 1
  • 10
  • 20
  • You use `let` inside your solution. I would at least mention `let` inside *"but as `const` declarations are block scoped"*, otherwise you might confuse the reader. – 3limin4t0r Jul 21 '20 at 13:38
  • @3limin4t0r I always replace `var` with `let` when I can while answering questions because `var` is not longer recommended from a while. However, in this case, declaring `i` by using `let` or `var` makes no difference for the result. But yes! You are right, `let` and `const` are both block scoped! Indeed `currentIndex` could have also been declared using `let`. – Ernesto Stifano Jul 21 '20 at 13:53
  • For some reason my eyes skipped over the `const currentIndex = i` line. Replacing `var i` with `let i` is enough to solve the issue. There is no reason to add an additional `currentIndex` variable. – 3limin4t0r Jul 21 '20 at 14:02
  • @3limin4t0r again you are right. I've always thought that declaring a variable using `let` at a `for` loop initilaization time would however create a common higher context for every cycle (since the declaration is placed outside the brackets). That is very interesting, I will update my answer accordingly. – Ernesto Stifano Jul 21 '20 at 14:20
0

I would suggest that you can pass the index along with username to the method that is returning the profile information. Then alongwith the data you can add this index so that you can get the index for which the data has been fetched.

I am showing you code that you can use and replace your code of lines with the below lines. Please update your method that is used for fetching the data.

for (var i = 0; i < this.all_data.length; i++) {
    this.moduleGetUserProfileByUserName({
      username: this.all_data[i].userCreated,
      index:i
    }).then(data => {
      this.user_data = data.data;
      let index=data.index
      this.all_data[index]=user_data
      console.log(this.user_data);
    });
}
Minal Shah
  • 1,402
  • 1
  • 5
  • 13