从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
相关产品推荐
相关产品推荐

