0

I'm trying to return an array of objects to a function, and looking at the debugger, it looks like it just returns an empty array.

Here's the function that I'm hoping to use:

// load from json file
  loadData(filepath) {
    let rooms = [];

    fetch(filepath)
      .then(
        res => res.json()
      )
      .then(function (data) {
        // console.log(data);
        for (let i = 0; i < data.rooms.length; i++) {
          rooms.push(data.rooms[i]);
        }
      });
    return rooms;
  }

I go into the debugger, and I see the rooms from data.rooms getting pushed to my local rooms object, but when I get back up to my init() function that's supposed to use this rooms data:

let rooms = this.loadData(this.datapath); // TODO: make games load from json data

    for (let i = 0; i < rooms.length; i++) {
      this.addRoom(rooms[i].name, rooms[i].getText, rooms[i].prompts, rooms[i].requirements);
    }

It looks like it's passed an empty array. Is there a scoping issue or something I'm missing? I'm not very experienced with fetch/promises/JSON.

Happy to provide any further info that may be useful. Thanks!

Casey
  • 31
  • 1
  • 5
  • Is the data that you are trying to read in your local or over a web server? – Sarath P S Dec 08 '19 at 19:54
  • Your code will immediately return rooms (last line). You are working with asynchronous code. The fetch function is asynchronous. It needs some time to do its work. – Karlan Dec 08 '19 at 19:55
  • @SarathPS I'm loading in the JSON from the web. I've confirmed that the JSON is successfully being loaded. – Casey Dec 08 '19 at 19:57
  • @Karlan thanks -- is there a way to make it wait for the for loop to finish? – Casey Dec 08 '19 at 19:57
  • You can return the fetch function. And then do loadData.then() or maybe async/await is even easier. – Karlan Dec 08 '19 at 20:00

2 Answers2

1

The problem is that your local variable rooms will be returned before the async fetch finish.

You can just simple await the fetch statements and make the function async:

async loadData(filepath) {
  let rooms = [];

  const response = await fetch(filepath);
  const data = await response.json();

  console.log(data);

  for (let i = 0; i < data.rooms.length; i++) {
      rooms.push(data.rooms[i]);
  }
  return rooms;
}

let rooms = await this.loadData(this.datapath);
Martin Godzina
  • 1,470
  • 11
  • 17
  • Thanks, I'm getting an Uncaught ReferenceError: regeneratorRuntime is not defined. I'm using browserify to bundle this js, could that be the issue? – Casey Dec 08 '19 at 20:13
  • You need to set up your browserify to support async await -> https://stackoverflow.com/questions/33527653/babel-6-regeneratorruntime-is-not-defined – Martin Godzina Dec 08 '19 at 20:22
  • Thanks... I installed browserify globally. would this make any difference when trying to install these babel plugins? I don't have a package.json, a .babelrc file, etc. Do I need to put these in the folder that I'm trying to browserify? (sorry, this is my first time using these tools! Thanks for your help!) – Casey Dec 08 '19 at 20:42
0

Try this, if it did not work let me know.

// load from json file
async function call() {
  const loadData = async filepath => {
    let rooms = [];

    return await fetch(filepath)
      .then(res => res.json())
      .then(async data => {
        rooms = await [...data];
        return rooms;
      });
  };

  let x = await loadData("https://jsonplaceholder.typicode.com/posts");
  console.log("TEST: ", x);
}
call();