0

A lot of my script is contingent on information first read from a .JSON file using fetch() and .json() so it's asynchronous. I need to delay the execution of the rest of my script until those functions finish, without sticking the rest of my code in a huge .then() or function block or something. I've done some searching around but I can't really find what I'm looking for.

let config;

fetch(chrome.runtime.getURL("../config.json"))
  .then(response => response.json())
  .then(json => config = json);

console.log(config);
// REST OF SCRIPT

It should log the config JSON object or the promise but, obviously, it only returns undefined. Any help would be greatly appreciated!

Quoc Tran
  • 45
  • 5

3 Answers3

1

Your config is being read before the request comes back. You can add another then clause:

let config;

fetch(chrome.runtime.getURL("../config.json"))
  .then(response => response.json())
  .then(json => config = json)
  .then(() => {
     console.log(config);
   });
Vaughan Hilts
  • 2,839
  • 1
  • 20
  • 39
  • I'd like to access the ```config``` object in various places throughout the rest of the script, so I don't really want to put the entire rest of the script in one ```then``` clause if it can be helped. – Quoc Tran May 27 '19 at 03:54
  • 1
    You're going to have to do this one way or another, since it's "async" If you want to "simulate" it outside of a "then" you can use `async` and `await` but keep in mind it's merely simulating the above, it's syntax sugar. – Vaughan Hilts May 27 '19 at 03:55
  • 1
    It can't be helped. It's promises all the way down. – Herohtar May 27 '19 at 03:56
  • you can write a promise-returning wrapper called getConfig() that caches the config the first time, if you're worried about performance. – dandavis May 27 '19 at 04:00
0

you can use this:

fetch(chrome.runtime.getURL("../config.json"))
    .then(response => response.json())
    .then(config => console.log(config));

Or:

const response = await fetch(chrome.runtime.getURL("../config.json"));
const config = await response.json();
config => console.log(config)
Ziv Ben-Or
  • 1,149
  • 6
  • 15
0

You only have one thread to work with, so there's no getting around the fact that you need to perform the async fetch of you config and then get on with the rest of your program. Most javascript is event driven, so this isn't typically a big issue. You can write in a style where the primary entrance to your code is a main() function, then you can just call it with the config after it's fetched:

fetch(chrome.runtime.getURL("../config.json"))
  .then(response => response.json())
  .then(main);

function main(config){
  // do stuff


}

Any substantially large code-base will be refactored into smaller functions anyway, so ideally your main function should not really be that large to begin with.

Mark
  • 90,562
  • 7
  • 108
  • 148
  • Huh. I was kinda hesitant just to wrap my entire script in a ```then``` but separating it into a ```main()``` like in other languages is a really good way to look at it. Thanks! Also, when you do a ```then(function);``` does it just call that function and pass the promised value to that function as an argument? – Quoc Tran May 27 '19 at 05:37
  • Yes. `then()` takes a function. So you could do `then(config => main(config))`, but that just adds a level of indirection in this case since `main` is already a function. – Mark May 27 '19 at 05:42