简体   繁体   中英

Singleton config - how to avoid returning a Promise in typescript

I have my Configuration class:

interface ConfigObject {
  apiUrl: string;
  identityPoolId: string;
  identityPoolRegion: string;
  region: string;
  userPoolId: string;
  userPoolWebClientId: string;
}

class Configuration {
  private static _instance: ConfigObject;

  public static get Instance() {
    return (
      this._instance ||
      this.getConfig<ConfigObject>().then((config) => {
        this._instance = config;
        return config;
      })
    );
  }

  private static async getConfig<TConfig>(): Promise<TConfig> {
    const response = await fetch('env.json', {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    });
    if (!response.ok) {
      throw new Error(response.statusText);
    }
    const data = await response.json();
    return data;
  }
}

export default Configuration.Instance;

and I want to access it's values in my service:

export default class APIService {
  static baseURL: string = `${Config.apiUrl}/mocked`;

Yet at the time of accessing Config.apiUrl is undefined

How can I make sure that the getConfig fetch gets executed and the actual object is returned instead?

You can't make an asynchronous process synchronous. But you can make your module wait to load until you've read that JSON file, by using top-level await , which is now broadly supported in browsers and by bundlers.

function getConfigData() {
    const response = await fetch('env.json', {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    });
    if (!response.ok) {
      throw new Error(response.statusText);
    }
    const data = await response.json();
    return data;
}
const data = await getConfigData(); // *** Module load waits here

class Configuration {
    private static _instance: ConfigObject;

    public static get Instance() {
        if (!this._instance) {
            this._instance = data;
        }
        return this._instance;
    }
}

export default Configuration.Instance;

That said, there doesn't seem to be any purpose to the Configuration class, just export the data directly:

function getConfigData() {
    const response = await fetch('env.json', {
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    });
    if (!response.ok) {
      throw new Error(response.statusText);
    }
    const data = await response.json();
    return data;
}
const data = await getConfigData(); // *** Module load waits here

export default data;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM