Node.js:等待请求
Node.js: Awaiting a Require
我是 Node.js
的新手,我一直在处理第三方提供商的示例项目,我正在尝试使用 Azure Key Vault 来存储配置值。
在执行其余部分之前,我无法让进程到达 wait
。我会尽可能详细地说明。
sample project has a file named agent.js
which is the start page/file. On line 16 (agent_config = require('./config/config.js')[process.env.LP_ACCOUNT][process.env.LP_USER]
) 它调用带有值的配置文件。我正在尝试使用 Key Vault 设置这些值。我尝试了多种调用函数组合,甚至实现了 async / await
,但 agent_config
的值始终包含一个 [Promise]
对象,而不是 Key Vault 返回的数据。
如果我是对的,这是因为 Key Vault 本身也使用 async / await
并且在返回 Key Vault 值之前使用配置文件 returns。
在这种情况下,Key Vault 怎么可能 added/implemented?
这是我尝试过的方法:
首次更新agent.js至
let agent_config = {};
try {
agent_config = require('./config/config.js')['123']['accountName'];
} catch (ex) {
log.warn(`[agent.js] Error loading config: ${ex}`)
}
console.log(agent_config);
测试 1
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
function getValue(secretName, secretVersion) {
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' }).then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
module.exports = {
'123': {
'accountName': {
accountId: getValue('mySecretName', '')
}
}
};
结果
{ accountsId: undefined }
测试 2
使 getValue 成为一个 async
函数并将其包裹在另一个函数周围(尝试不包裹但也不起作用)
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
async function getValue(secretName, secretVersion) {
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' }).then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
async function config() {
module.exports = {
'123': {
'accountName': {
accountId: await getValue('mySecretName', '')
}
}
};
}
config();
结果
{}
测试 3
使 getValue 成为一个 async
函数并将其包裹在另一个函数周围(尝试不包裹但也不起作用)
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
async function getValue(secretName, secretVersion) {
return msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
module.exports = {
'123': {
'accountName': {
accountId: getValue('mySecretName', '')
}
}
};
config();
结果
{ accountId: { <pending> } }
其他
我尝试了很多其他方法,例如 module.exports = async (value) =< {...}
(通过其他 questions/solutions 找到但没有成功。
我开始觉得我需要在 agent.js
上做一些 "waiting",但我还没有找到这方面的好信息。
任何帮助都会很棒!
一个问题是您的 getValue
函数没有 returning 任何东西,因为您的 return 需要明确。
(没有 returned 的承诺,没有什么可等待的)
async function getValue(secretName, secretVersion) {
return msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
您也可以使用箭头函数使用不太明确的 returns..
const getValue = async (secretName, secretVersion) =>
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then(credentials => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion)
.then(response => response.Value);
});
引入异步的 Azure Key Vault 读取意味着您的整个配置读取是异步的。你无能为力。这意味着使用配置的代码需要适当地处理它。您首先导出一个异步函数,该函数将 return 配置..
async function getConfig() {
return {
'123': {
'accountName': {
accountId: await getValue('mySecretName', '')
}
}
};
}
module.exports = getConfig;
在您的代理代码中调用该函数。这将意味着您的代理代码也需要包装在一个函数中,所以可能是这样的..
const Bot = require('./bot/bot.js');
const getConfig = require('./config/config.js');
getConfig().then(agentConfig => {
const agent = new Bot(agentConfig);
agent.on(Bot.const.CONNECTED, data => {
log.info(`[agent.js] CONNECTED ${JSON.stringify(data)}`);
});
});
包 azure-keyvault
已被弃用,取而代之的是新包来分别处理 Keyvault 密钥、机密和证书。对于您的方案,您可以使用新的 @azure/keyvault-secrets package to talk to Key Vault and the new @azure/identity 包来创建凭据。
const { SecretClient } = require("@azure/keyvault-secrets");
const { DefaultAzureCredential } = require("@azure/identity");
async function getValue(secretName, secretVersion) {
const credential = new DefaultAzureCredential();
const client = new SecretClient(KEY_VAULT_URI, credential);
const secret = await client.getSecret(secretName);
return secret.value;
}
DefaultAzureCredential
假定您已经设置了以下环境变量
- AZURE_TENANT_ID: Azure Active Directory 中的租户 ID
- AZURE_CLIENT_ID:在AAD租户中注册的应用程序(客户端)ID
- AZURE_CLIENT_SECRET: 已注册应用程序的客户端密码
要尝试其他凭据,请参阅 readme for @azure/identity
如果您要从旧的 azure-keyvault 包迁移,请查看 migration guide 以了解主要变化
我是 Node.js
的新手,我一直在处理第三方提供商的示例项目,我正在尝试使用 Azure Key Vault 来存储配置值。
在执行其余部分之前,我无法让进程到达 wait
。我会尽可能详细地说明。
sample project has a file named agent.js
which is the start page/file. On line 16 (agent_config = require('./config/config.js')[process.env.LP_ACCOUNT][process.env.LP_USER]
) 它调用带有值的配置文件。我正在尝试使用 Key Vault 设置这些值。我尝试了多种调用函数组合,甚至实现了 async / await
,但 agent_config
的值始终包含一个 [Promise]
对象,而不是 Key Vault 返回的数据。
如果我是对的,这是因为 Key Vault 本身也使用 async / await
并且在返回 Key Vault 值之前使用配置文件 returns。
在这种情况下,Key Vault 怎么可能 added/implemented?
这是我尝试过的方法:
首次更新agent.js至
let agent_config = {};
try {
agent_config = require('./config/config.js')['123']['accountName'];
} catch (ex) {
log.warn(`[agent.js] Error loading config: ${ex}`)
}
console.log(agent_config);
测试 1
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
function getValue(secretName, secretVersion) {
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' }).then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
module.exports = {
'123': {
'accountName': {
accountId: getValue('mySecretName', '')
}
}
};
结果
{ accountsId: undefined }
测试 2
使 getValue 成为一个 async
函数并将其包裹在另一个函数周围(尝试不包裹但也不起作用)
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
async function getValue(secretName, secretVersion) {
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' }).then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
async function config() {
module.exports = {
'123': {
'accountName': {
accountId: await getValue('mySecretName', '')
}
}
};
}
config();
结果
{}
测试 3
使 getValue 成为一个 async
函数并将其包裹在另一个函数周围(尝试不包裹但也不起作用)
./config/config.js
const KeyVault = require('azure-keyvault');
const msRestAzure = require('ms-rest-azure');
const KEY_VAULT_URI = 'https://' + '{my vault}' + '.vault.azure.net/' || process.env['KEY_VAULT_URI'];
async function getValue(secretName, secretVersion) {
return msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
module.exports = {
'123': {
'accountName': {
accountId: getValue('mySecretName', '')
}
}
};
config();
结果
{ accountId: { <pending> } }
其他
我尝试了很多其他方法,例如 module.exports = async (value) =< {...}
(通过其他 questions/solutions 找到但没有成功。
我开始觉得我需要在 agent.js
上做一些 "waiting",但我还没有找到这方面的好信息。
任何帮助都会很棒!
一个问题是您的 getValue
函数没有 returning 任何东西,因为您的 return 需要明确。
(没有 returned 的承诺,没有什么可等待的)
async function getValue(secretName, secretVersion) {
return msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then((credentials) => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion).then(
function (response) {
return response.Value;
});
});
}
您也可以使用箭头函数使用不太明确的 returns..
const getValue = async (secretName, secretVersion) =>
msRestAzure.loginWithAppServiceMSI({ resource: 'https://vault.azure.net' })
.then(credentials => {
const client = new KeyVault.KeyVaultClient(credentials);
return client.getSecret(KEY_VAULT_URI, secretName, secretVersion)
.then(response => response.Value);
});
引入异步的 Azure Key Vault 读取意味着您的整个配置读取是异步的。你无能为力。这意味着使用配置的代码需要适当地处理它。您首先导出一个异步函数,该函数将 return 配置..
async function getConfig() {
return {
'123': {
'accountName': {
accountId: await getValue('mySecretName', '')
}
}
};
}
module.exports = getConfig;
在您的代理代码中调用该函数。这将意味着您的代理代码也需要包装在一个函数中,所以可能是这样的..
const Bot = require('./bot/bot.js');
const getConfig = require('./config/config.js');
getConfig().then(agentConfig => {
const agent = new Bot(agentConfig);
agent.on(Bot.const.CONNECTED, data => {
log.info(`[agent.js] CONNECTED ${JSON.stringify(data)}`);
});
});
包 azure-keyvault
已被弃用,取而代之的是新包来分别处理 Keyvault 密钥、机密和证书。对于您的方案,您可以使用新的 @azure/keyvault-secrets package to talk to Key Vault and the new @azure/identity 包来创建凭据。
const { SecretClient } = require("@azure/keyvault-secrets");
const { DefaultAzureCredential } = require("@azure/identity");
async function getValue(secretName, secretVersion) {
const credential = new DefaultAzureCredential();
const client = new SecretClient(KEY_VAULT_URI, credential);
const secret = await client.getSecret(secretName);
return secret.value;
}
DefaultAzureCredential
假定您已经设置了以下环境变量
- AZURE_TENANT_ID: Azure Active Directory 中的租户 ID
- AZURE_CLIENT_ID:在AAD租户中注册的应用程序(客户端)ID
- AZURE_CLIENT_SECRET: 已注册应用程序的客户端密码
要尝试其他凭据,请参阅 readme for @azure/identity 如果您要从旧的 azure-keyvault 包迁移,请查看 migration guide 以了解主要变化