0

i have this code:

let splatshArtData = [];
splatshArt.getSplatchArt(participants[i].championId).then((splatshArtUrl) => {
    splatshArtData.push(splatshArtUrl);                 
});
console.log(splatshArtData);

I want add the "splatshArtUrl" to my array, but this don't work, when i try print the data this don't print nothing, i don't know how to do that, any idea?

Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
  • What does `.save` method ? – Mihai Alexandru-Ionut Feb 18 '17 at 09:37
  • @Alexandru-IonutMihai oh, nothing, a dirty code :p – Jonathan Perez Feb 18 '17 at 09:43
  • 1
    Move your `console.log(splatshArtData);` into the `.then()` block and it will work. Your function call is asynchronous but you treat it like it's synchronous, thus the error. – Daniel B Feb 18 '17 at 09:45
  • Another method is to use a `callback` function. – Mihai Alexandru-Ionut Feb 18 '17 at 09:45
  • A callback would remove the need to use promises, and also alot of the elegance to the code. – Daniel B Feb 18 '17 at 09:46
  • @DanielB but, i need promise, why i used a package(httpinvoke for nodejs), and this return all in promise, any idea? – Jonathan Perez Feb 18 '17 at 09:50
  • Yes, as I previously commented, it **does** work. Your problem is that you are printing (`console.log`) the array before it's been populated. If you do as I said and move the print into the `.then()` block after the `.push()`, you'll see that the array has content. If you want anything more than just printing out the values, you'll have to be more specific in your question. – Daniel B Feb 18 '17 at 09:56
  • @DanielB I need to pass the variable to another function, but this must be from without of .then – Jonathan Perez Feb 18 '17 at 10:05
  • Possible duplicate of [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](http://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Andreas Feb 18 '17 at 10:22

3 Answers3

0

Try this:

let splatshArtData = [];
splatshArt.getSplatchArt(participants[i].championId).then((splatshArtUrl) => {
    splatshArtData.push(splatshArtUrl); 
    console.log(splatshArtData);                
});

The function inside the then runs right after the asynchronous function getSplatchArt resolves it's promise, so it was running the console.log before the item is added to the array.

Omri Luzon
  • 3,975
  • 6
  • 20
  • 29
  • That's not really correct. Sure this works, but the function in the `.then()` clearly doesn't run "*right after the asynchronous function*". It will run when the promise returned from `getSplatchArt` is resolved, which *could* be right after, but it could also be 10 minutes after. – Daniel B Feb 18 '17 at 10:02
  • I didn't want to confuse him, because he didn't seem to understand what the promise does. – Omri Luzon Feb 18 '17 at 10:05
  • Well, you should be clear on how it works since what your answer now is saying is incorrect. – Daniel B Feb 18 '17 at 10:08
0

The problem that you're facing here is that getSplatchArt returns a promise, and promises take time to resolve. You can therefore never guarantee that splatshArtData.push(splatshArtUrl); will run before the console.log.

The solution is to move all logic which requires data returned from the promise to within the promise callback. This can of course include calls to other functions.

// function to process the splashArtData - will be called from the promise
// when the promise is resolved.
function processSplashArt(data) {
  // this will now print as you are expecting
  console.log(data);
}

let splatshArtData = [];

splatshArt.getSplatchArt(participants[i].championId).then((splatshArtUrl) => {
  splatshArtData.push(splatshArtUrl);    

  // pass the splashArtData to the callback function - it's now ready
  processSplashArt(slashArtData);         
});
clinton3141
  • 4,751
  • 3
  • 33
  • 46
0

JavaScript is synchronous, thus each line of code will be executed right after one another.

If we annotate your code with line numbers like below

1. let splatshArtData = [];
2. splatshArt.getSplatchArt(participants[i].championId).then((splatshArtUrl) => {
3.     splatshArtData.push(splatshArtUrl);                 
   });
4. console.log(splatshArtData);

you are assuming that it will run in the order of 1, 2, 3, 4, while in reality it will run in the order of 1, 2, 4, 3. Why is that? Because JavaScript is synchronous, and the function at line 2 is asynchronous, meaning that you'll have to await that before you can continue. If you don't the splatshArtData variable will be an empty array since the data hasn't been fetched yet.

If you want to return the fetched data and use it in another function, you shouldn't mix it will callbacks as suggested in another answer, but instead chain the promise and use the resolved value from the function that fetches the data.

function getSplatshArt() {
    let splatshArtData = [];

    //Return a promise
    return splatshArt.getSplatchArt(participants[i].championId).then((splatshArtUrl) => {
        console.log(splatshArtData); //this will log out the data
        splatshArtData.push(splatshArtUrl);  
        return splatshArtData; //this will be the resolved value from the promise 
    });
}

//Call the function and access the resolved data in the .then() block
getSplatshArt()
    .then(data => {
        console.log(data); //this is the data returned from the getSplatshArt function
    });

Looking at your code, I get the impression that you're looping over an array of ID's, and if you want to fetch multiple values at once, this wont work since you have to handle multiple promises. But that is another question and I think you should do some more research of your own before asking about that.

Daniel B
  • 8,770
  • 5
  • 43
  • 76