You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Azure App Configuration加载设置返回Promise而非对象的问题

问题描述

需要从Azure App Configuration中获取值,赋值给单例类内的settings属性,预期得到如下键值对对象:

{ TESTVAL1: 'Giggity Giggity ;-)', TESTVAL2: 'testing123', TESTVAL3: 'here we are again' }

预期类初始化时完成设置加载,供应用其他部分调用。但当前代码中settings属性返回的是Promise而非目标对象,相关代码如下:

class AppConfiguration { 
  private _settings: any // for now 
  private _client = new AppConfigurationClient(process.env.AZURE_APPCONFIG_CONNECTION_STRING || ''); 
  private static _instance: AppConfiguration;

  constructor() { 
    this._settings = this.loadSettings(); 
  } 

  public getInstance() { 
    this.log(['AppConfiguration Initialized...']) 
    return AppConfiguration._instance !== null ? AppConfiguration._instance : new AppConfiguration() 
  } 

  private loadSettings = async() => { 
    let loadedSettings: ConfigVars = {} 
    const filteredSettings: AsyncIterableIterator<ConfigurationSetting<string>> = await this._client.listConfigurationSettings({ labelFilter: process.env.AZURE_CONFIG_LABEL }); 
    for await (const setting of filteredSettings) { 
      if (!setting.key.includes(featureFlagPrefix)) { 
        const obj: any = {}; 
        obj[setting.key] = setting.value 
        loadedSettings = {...loadedSettings, ...obj} 
      } 
    } 
    return loadedSettings; 
  } 

  public get settings(): ConfigVars { 
    // returns a promise, should return an object 
    return this._settings; 
  } 

  public getSetting = (key: string) => { 
    return (async () => { return await this._settings })().then(setting => { return setting[key] }) 
  } 
} 

const config = new AppConfiguration() 
export default config.getInstance();

调用时出现如下问题:

import config from './AppConfig', ... 

// val1 is undefined 
const val1 = config.settings.TESTVAL1 
// val2 is a <Promise> 
const val2 = config.getSetting('TESTVAL1') 

请问如何让settings返回对象而非Promise?

解决方案

核心问题是构造函数无法异步执行,直接把async函数loadSettings()的返回值(Promise)赋值给了_settings,导致settings getter返回Promise。以下是可行的解决方式:

方案1:静态异步方法初始化单例(推荐)

修改类的实现,通过静态异步方法完成单例初始化和配置加载,确保实例可用前配置已就绪:

class AppConfiguration { 
  private _settings: ConfigVars;
  private _client = new AppConfigurationClient(process.env.AZURE_APPCONFIG_CONNECTION_STRING || ''); 
  private static _instance: AppConfiguration;

  // 私有构造函数,禁止外部直接实例化
  private constructor() {} 

  // 静态异步方法,负责初始化单例并加载配置
  public static async getInstance(): Promise<AppConfiguration> {
    if (!AppConfiguration._instance) {
      AppConfiguration._instance = new AppConfiguration();
      // 等待配置加载完成后再赋值给_settings
      AppConfiguration._instance._settings = await AppConfiguration._instance.loadSettings();
      console.log('AppConfiguration Initialized...');
    }
    return AppConfiguration._instance;
  } 

  private async loadSettings(): Promise<ConfigVars> { 
    let loadedSettings: ConfigVars = {} 
    const filteredSettings = await this._client.listConfigurationSettings({ 
      labelFilter: process.env.AZURE_CONFIG_LABEL 
    }); 
    for await (const setting of filteredSettings) { 
      if (!setting.key.includes(featureFlagPrefix)) { 
        // 简化赋值逻辑,无需临时对象
        loadedSettings[setting.key] = setting.value;
      } 
    } 
    return loadedSettings; 
  } 

  public get settings(): ConfigVars { 
    return this._settings; 
  } 

  public getSetting(key: string): string | undefined { 
    // 直接返回配置值,无需处理Promise
    return this._settings[key];
  } 
} 

// 导出异步获取实例的方法
export default AppConfiguration.getInstance();

调用调整

由于getInstance()是异步方法,需要在应用启动阶段等待配置加载完成:

// 应用入口文件
import getConfig from './AppConfig';

async function bootstrap() {
  const config = await getConfig;
  
  // 现在可直接访问配置值
  const val1 = config.settings.TESTVAL1;
  const val2 = config.getSetting('TESTVAL1');
  
  // 启动应用逻辑
}

bootstrap();

关键修改说明

  • 将单例初始化改为异步静态方法,确保配置加载完成后再返回实例
  • 构造函数设为私有,避免外部创建未加载配置的无效实例
  • 简化loadSettings中的赋值逻辑,减少不必要的临时对象
  • getSetting现在直接返回配置值,无需再处理Promise嵌套

内容的提问来源于stack exchange,提问作者Scotty Compton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 14:47:35