0

Why array argument is not visible in second then?

let assignDataToArray = (array) => {
    fetch("data.json")
        .then(response => {
            if (response.ok)
                return response.json();
            else
                throw new Error("Something went wrong with json file");
        })
        .then(result => array = [...result.data])
        .catch(error => console.log(error));
}

let myArray = [];
assignDataToArray(myArray);
console.log(myArray);

I use VS Code and there is even pointed that array argument is not visible in scope of second then. In result the promise returns empty Array and nothing is assigned to array argument.

  • 2
    `fetch` is async. you can't simply return from an async function. – Daniel A. White Mar 02 '20 at 19:30
  • 2
    By using `array =`, you are also losing the reference to that Array. See this: https://stackoverflow.com/questions/44660024/replace-array-elements-without-losing-reference – blex Mar 02 '20 at 19:31

1 Answers1

1

As you can see in the comments, you have multiple problems here.

  1. fetch is asynchronous. Your program will keep running while the fetch does its thing and runs what's in .then. Hence, your console.log is executed before the data is recovered.

  2. By doing array = ..., you are creating a new Array, which won't have the same reference as the one you assigned to myArray. You can solve this by mutating the original Array instead of using variable assignment (=).

Here is a way using async/await:

let assignDataToArray = (array) => {
    return fetch("data.json") // <----- Notice the return
        .then(response => {
            if (response.ok)
                return response.json();
            else
                throw new Error("Something went wrong with json file");
        })
        .then(result => array.splice(0, array.length, ...result.data)) // Use of splice
        .catch(error => console.log(error));
}

async function main() { // await can only be used inside an `async` function
  let myArray = [];
  await assignDataToArray(myArray); // <- await waits for this before running the next line
  console.log(myArray);
}
main();

Or using simple Promises:

let assignDataToArray = (array) => {
    // ... same code as above ...
}

let myArray = [];
assignDataToArray(myArray)
  .then(() => {
    console.log(myArray);
    /* Do something else from here */
  });
blex
  • 24,941
  • 5
  • 39
  • 72