我对依赖第一个require()的基于Express的node.js应用程序有疑问。这是我的第一个node.js应用程序。第一个require()命中AWS ec2参数存储以收集数据库的凭证。在此需求以异步方式解决之前,我无法建立与数据库的连接。
我发现做到这一点的最好方法是导出一个回调,并将其余的require()语句包装在第一个require()的回调中。 这是不好的做法吗?
//app.js
var appConfig = require('./config/appconfig');
appConfig.fetchAppConfig(function(err, result) {
if(err) {
console.log(err);
console.error("Server failed to startup. Config parameters not available.");
}
else {
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
...
app.use(bodyParser.json());
etc
...
//appConfig.js
module.exports = function fetchAppConfig(callback) {
getCredentials(function(err, result) {
if(err) {
console.log(err);
callback(err);
} else {
awsLogin.paramStoreService(result).then(
data => {
appConfig = decodeAppConfig(data.Parameter.Value);
callback(null, appConfig);
}
).catch(
error => {
console.error(error);
callback(err);
}
)
}
})
}
我错过了一个更简单的选择吗?
让我更好地使用这种逻辑将配置提取到部署代码中的某处?
答案 0 :(得分:0)
我将定义几个函数,一个函数用于请求凭据,而另一个函数则在检索到凭据后连接到数据库。您可以使用async模块的series函数来轻松地控制应用程序的流程。
从文档中:
依次运行任务集合中的功能,每个功能都在运行 一旦上一个功能完成。如果有任何功能 系列将错误传递给其回调,不再运行任何函数,并且 立即使用错误值调用回调。除此以外, 任务完成后,回调会收到一系列结果。
这是一个例子:
var async = require('async');
function getCredentials(callback) {
callback(null, {
user: 'hello',
pass: 'world',
});
};
function connectToDatabase(callback, creds) {
console.log('Connecting to database => ' + JSON.stringify(creds));
callback(null, 'Done');
};
async.series([
getCredentials,
connectToDatabase,
],
function(err, results) {
console.error(err);
console.log(results);
});
答案 1 :(得分:0)
直到节点支持顶级等待,以下是我针对此确切用例使用的解决方案。
// index.js
(async () => {
await require('./config').initialize();
require('./app');
})();
// config.js
const _ = require('lodash');
const secretKeys = ['secret1', 'secret2'];
const parameterHierarchyPrefix = `/${process.env.NODE_ENV}/app/`;
const getParamNameWithoutHierarchy = name => _.replace(name, new RegExp(`${parameterHierarchyPrefix}(.*)`), '$1');
const config = {};
config.initialize = async (callback = () => {}) => {
try {
// initialize aws sdk and ssm
const AWS = require('aws-sdk');
AWS.config.update({
region: 'us-west-2',
accessKeyId: S3_ACCESS_KEY,
secretAccessKey: S3_SECRET,
});
const ssm = new AWS.SSM();
// map secret keys to lowercase
const secretNames = _.map(secretKeys, key => `${parameterHierarchyPrefix}key`);
// this api only allows fetching 10 params per call
const secretFetchBatches = _.chunk(secretNames, 10);
// fetch secrets from aws parameter store
let secrets = {};
for (let i = 0; i < _.size(secretFetchBatches); i += 1) {
const parameters = await ssm.getParameters({
Names: secretFetchBatches[i],
WithDecryption: true,
}).promise();
secrets = {
...secrets,
..._.zipObject(_.map(parameters.Parameters, ({ Name }) => ([getParamNameWithoutHierarchy(Name)])), _.map(parameters.Parameters, 'Value')),
};
}
// write the secrets into the config object
_.each(secrets, (v, k) => constants[k] = v);
// invoke the callback
callback();
} catch (e) {
throw e
}
};
module.exports = config;