Я попытался найти решение своей проблемы, но не смог его найти и искал несколько «примеров передовой практики». У меня есть экспресс-приложение nodejs, и мои функции разделены на файлы. Например, у меня есть этот контроллер (oktacontroller.js):
var okta_api_key = <here some await data, getting from db>;
const OKTA_ORG_URL = '<here too>';
exports.createUser = async (req, res) => {
console.info(okta_api_key);
}
exports.getGroups = async (req, res) => {
console.info(okta_api_key);
}
В обеих экспортируемых функциях (которые являются экспресс-маршрутами) мне нужен var okta_api_key. Я знаю, что могу получить их, запросив их в обеих функциях, потому что они являются асинхронными функциями, и я могу использовать там ожидание, но мне кажется глупым запрашивать это каждый раз (потому что это никогда не изменится).
Как мне с этим справиться? Я знаю, что я могу сделать это:
var okta_api_key;
(async () => {
okta_api_key = await <getting key async>
})()
Но это тоже нехорошо..
Есть ли способ сделать какую-то большую функцию, которая является асинхронной и экспортирует две функции? Другими словами: как использовать ожидание на верхнем уровне файла (модуля). Это не обязательно должно быть на верхнем уровне (это невозможно), но какой-то метод, чтобы мои переменные «верхнего уровня» были доступны моим экспортированным функциям.
EDIT: какой-то другой вариант использования, потому что мне предложили поместить его в файл конфигурации. Да, для этого возможно, но, например: у меня есть какой-то другой ключ API, который получает свой токен доступа от самой службы при каждом запуске (потому что срок его действия истекает). Этот токен нельзя сохранить в файле конфигурации, поэтому мне нужна асинхронная работа, чтобы получить значение. Я знаю, что ожидание верхнего уровня не работает (или даже нежелательно), но мне просто нужен пример того, как вы, ребята, сделали бы это, если бы это был ваш проект :)
Если он никогда не меняется, зачем его хранить в БД? Просто поместите его в файл конфигурации и импортируйте в свой модуль.
Да, но я могу (и хочу) менять настройки через графический интерфейс (мое приложение)
Простой. установите var okta_api_key
на обещание, которое вы можете ждать столько раз, сколько хотите, фактически не выполняя асинхронную задачу снова и снова.
Так что просто скажите const okta_api_key = doSomethingAsync(), а затем в функциях скажите const real_api_key = await okta_api_key()?
Вы близко:
var okta_api_key = (async () => {
return await <getting key async>
})();
Создайте обещание, а затем await
это обещание, когда захотите его использовать.
How do I use await on the top level of a file (module).
Верхний уровень await
может выглядеть великолепно: вы просто добавляете один await
, а затем получаете синхронный доступ к переменной. Но это слишком сильно упрощает: он остановит выполнение всех модулей, зависящих от этого модуля. В большинстве случаев вам это не нужно¹. Вместо этого создайте обещание асинхронной задачи, а затем ждите ее, когда это необходимо. Таким образом, вы ограничиваете асинхронное выполнение фрагментами кода, которые действительно в нем нуждаются.
¹ Эти редкие случаи:
1) Загрузка какого-то глобального конфига, к которому у вас есть доступ везде в вашем коде, поэтому нет смысла запускать службу, если конфиг не готов.
2) await
запись в файл верхнего уровня вашего сервиса: Поскольку от него не зависит ни один модуль, это не вызовет никаких проблем.
Боковое примечание: ожидание верхнего уровня еще не указано, и поддержки NodeJS также пока нет. Чтобы использовать его в производстве, вам нужно подождать несколько месяцев (?).
Спасибо, похоже, это работает (ваш пример), НО возвращает обещание <ключ здесь>. Я просто хочу веревку. Итак, обещание разрешено правильно, но okta_api_key не содержит правильного значения.
Кстати, как бы вы справились с этим?
да. await
это обещание и все в порядке.
на ТЛ нельзя?
var okta_api_key = (async () => { return await process.env.OKTA_API_KEY; })(); не работает, потому что в okta_api_key есть Promise <akjhdkajbckjsygdfkjh(настоящий ключ API)>
Это хороший текст об асинхронных функциях в JS, но это не ответ на мой вопрос. Я хочу иметь var/const, который заполнен асинхронными данными (поэтому не сразу), чтобы быть доступным для двух функций, которые объявлены позже в файле.
Нет, ты этого не хочешь. Поверьте мне.
Точно, так как бы вы решили это? Это то, что я не могу найти везде. TLA не подходит, но я не могу найти решения своей проблемы. Если у вас есть две функции, которым нужны одни и те же данные, что бы вы сделали?
Ах, я думаю, вы и Кевин Б. (ответил на исходный пост) имеете в виду одно и то же, не так ли? Тогда это путь, я думаю
Сделайте функции асинхронными, дождитесь обещания. И да, Кевин Б. говорит то же самое.
Извините за недоразумение, я отметил ваш ответ как ответ, большое спасибо. Теперь имеет больше смысла.
В настоящее время нет, это все еще Предложение 2 этапа, и я бы посоветовал прочитать это: Ожидание высшего уровня — это футган.