skip to Main Content

I have the below code where I make an API call and store the response to window. This is done in order to access the value anywhere in the application. But since rest of the application is dependent on this code i want to make this synchronous, that is, rest of the JS should execute only after the api call is done and data is stored to global object. What is the best way to solve this?

Note: This is a sample of the use case. I can’t use methods like .then as this is first import in an HTML file having several JS file each of them being dependent on the response of this.

    class GlobalConstants {
      constructor() {
        this.dynamicData = {}; 
        this.getConfigData(); 
      }
 
      async getConfigData() {
        try {
          const configResponse = await fetch("https://jsonplaceholder.typicode.com/todos/1");
          if (configResponse.status === 200) {
          const dummyData = await configResponse.json();
          this.dynamicUrl = dummyData;
          } else {
            throw new Error(`Config API threw ${formattedConfigResponse.status}`);
          }
        } catch (error) {
          console.warn("Failed to fetch:", error);
        }
      }
    }
    
window.globalConstants = new GlobalConstants();


console.log(globalConstants.dynamicData)

In the example, instead of consoling empty object it should ideally print the api response.

2

Answers


  1. You could return a promise from the constructor and return the object (this) inside of it, after your async function has finished.

    class SomeClass{
        constructor(){
            this.foo = "bar";
    
            return new Promise((resolve, reject) => {
               
                this.doSomething()
                .then(() => resolve(this))
                .catch(reject);
                
            });
        }
        async doSomething(){
        
        }
    }
    
    new SomeClass()
    .then(object => console.log(object));
    Login or Signup to reply.
  2. Short answer …

    "There is no way around async/await syntax, unless one wants to fall back to purely written promises."

    From both of my above comments …

    Your prototypal async getConfigData method does neither assign anything to an instance’s own dynamicData property, nor does it return any value. But instead it does assign an API response value to an instance’s own dynamicUrl property. My advice getConfigData should never assign anything to an instance’s property, but always return a value that can be awaited for e.g. like that …

    class GlobalConstants {
    
      async getConfigData() {
        let result = {};
    
        try {
          const configResponse =
            await fetch("https://jsonplaceholder.typicode.com/todos/1");
    
          if (configResponse.status === 200) {
    
            result = await configResponse.json();
          } else {
            throw new Error(`Config API threw ${formattedConfigResponse.status}`);
          }
        } catch (error) {
          console.warn("Failed to fetch:", error);
        }
        return result;
      }
    }
    const globalConstants = {};
    
    (async() => {
    
      const configData = await new GlobalConstants().getConfigData();
    
      Object.assign(globalConstants, configData);
    
      console.log({ globalConstants });
    
    })();
    
    console.log({ globalConstants });
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    … In addition, why would one choose a class based abstraction at all. It looks like there will be anyway just one instance of it with getConfigData too, seeing a one time use only. Why not making the latter a single globally or module scoped function which retrieves the data that needs to be awaited. There is no way around async/await.

    async function getConfigData() {
      let result = {};
    
      try {
        const configResponse =
          await fetch("https://jsonplaceholder.typicode.com/todos/1");
    
        if (configResponse.status === 200) {
    
          result = await configResponse.json();
        } else {
          throw new Error(`Config API threw ${formattedConfigResponse.status}`);
        }
      } catch (error) {
        console.warn("Failed to fetch:", error);
      }
      return result;
    }
    const globalConstants = {};
    
    (async() => {
    
      const configData = await getConfigData();
    
      Object.assign(globalConstants, configData);
    
      console.log({ globalConstants });
    
    })();
    
    console.log({ globalConstants });
    .as-console-wrapper { min-height: 100%!important; top: 0; }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search