我在加载由异步调用加载的配置变量时遇到问题。
如下所示的配置变量:
//config.js
let config = {
db: {
dev: {
client: ENV_VARS.dev_db_client,
host: ENV_VARS.dev_db_host,
name: ENV_VARS.dev_db_name,
user: ENV_VARS.dev_db_user,
password: ENV_VARS.dev_db_password,
min_pool: ENV_VARS.dev_db_min_pool,
max_pool: ENV_VARS.dev_db_max_pool
},
staging: {
client: ENV_VARS.staging_db_client,
host: ENV_VARS.staging_db_host,
name: ENV_VARS.staging_db_name,
user: ENV_VARS.staging_db_user,
password: ENV_VARS.staging_db_password,
min_pool: ENV_VARS.staging_db_min_pool,
max_pool: ENV_VARS.staging_db_max_pool
},
production: async function () {
let secret = await getSecretFromStore(`SECRET_NAME`);
let tmpConfig = JSON.parse(secret);
return {
client: ENV_VARS.production_db_client,
host: tmpConfig.host,
password: tmpConfig.password,
user: tmpConfig.username,
name: tmpConfig.db_name,
min_pool: ENV_VARS.production_db_min_pool,
max_pool: ENV_VARS.production_db_max_pool
};
});
},
NODE_ENV: ENV_VARS.NODE_ENV,
STACK_ID: ENV_VARS.STACK_ID,
};
module.exports = config;
//knexfile.js
const config = require('authenticator/config');
let productionConfig = {};
if (config.NODE_ENV == 'production') {
// how to load the production vars in the right way and export them?
//the next line is async call and it is wrong to call it like this
productionConfig = config.db.production();
}
const _config = {
development: {
client: config.db.dev.client,
connection: {
host: config.db.dev.host,
database: config.db.dev.name,
user: config.db.dev.user,
password: config.db.dev.password,
// debug: ['ComQueryPacket']
},
pool: {
min: Number(config.db.dev.min_pool) || 0,
max: Number(config.db.dev.max_pool) || 1
},
migrations: {
tableName: 'knex_migrations'
}
},
staging: {
client: config.db.staging.client,
connection: {
host: config.db.staging.host,
database: config.db.staging.name,
user: config.db.staging.user,
password: config.db.staging.password
},
pool: {
min: Number(config.db.staging.min_pool) || 0,
max: Number(config.db.staging.max_pool) || 1
},
migrations: {
tableName: 'knex_migrations'
}
},
production: {
client: productionConfig.client,
connection: {
host: productionConfig.host,
database: productionConfig.name,
user: productionConfig.user,
password: productionConfig.password
},
pool: {
min: Number(productionConfig.min_pool) || 0,
max: Number(productionConfig.max_pool) || 1
},
migrations: {
tableName: 'knex_migrations'
}
}
};
module.exports = _config;
//db.js
const config = require('config');
//the config are loaded into knexfile.js and used but production can't be loaded cuz it is async call
//the next line should call the production vars in the env is production
const knexConfig = require('../knexfile')[config.NODE_ENV];
const knex = require('knex')(knexConfig);
module.exports = knex;
那么,有什么好的策略可以将该模块加载到不同的node_module中?
换句话说,加载临时变量和dev变量并使用它们很容易,但是由于生产变量是通过异步调用加载的,那么如何以正确的方式加载它们?
如果使用发电机。这样可以解决问题吗?
答案 0 :(得分:1)
我要做的第一件事是使开发和登台配置具有与live相同的语义。由于production
返回了一个保证,因此dev
和staging
也应该返回一个保证。不这样做就是在为生产准备惊喜。
例如:
db: {
dev: async function() {
await delay(0); // Where `delay` is a `setTimeout` wrapper
return {
client: ENV_VARS.dev_db_client,
host: ENV_VARS.dev_db_host,
name: ENV_VARS.dev_db_name,
user: ENV_VARS.dev_db_user,
password: ENV_VARS.dev_db_password,
min_pool: ENV_VARS.dev_db_min_pool,
max_pool: ENV_VARS.dev_db_max_pool
};
},
// ....
...和分期相同。您甚至可能会看到延迟产生了多长时间,并模仿了dev
和staging
中的延迟。 (除非您返回当前的所有配置。)
您的production
也应该是async
函数,因为您在其中使用了await
。
您的下一步是删除该代码。您为所有三个配置都构建了相同的结构。将其集中在一个函数中:
function buildConfig(env) {
return {
client: env.client,
connection: {
host: env.host,
database: env.name,
user: env.user,
password: env.password,
// debug: ['ComQueryPacket']
},
pool: {
min: Number(env.min_pool) || 0,
max: Number(env.max_pool) || 1
},
migrations: {
tableName: 'knex_migrations'
}
};
}
然后,导出配置的承诺,而不是实际的配置:
module.exports = Promise.all([config.db.dev, config.db.staging, config.db.production])
.then(([dev, staging, production]) => {
return {
development: buildConfig(dev),
staging: buildConfig(staging),
production: buildConfig(production)
};
});
使用该模块的模块将需要使用该诺言,因为该操作是异步的(在所有环境中):
require(/*...*/).then(config => {
// Code using the config here...
});
在更长时间之前,多亏了top-level await
proposal,这将减轻痛苦(使用ESM模块,而不是CommonJS模块),它可以使模块解析为异步,并允许您在顶层使用await