Javascript/Typescript Exportar Const por defecto como valor desde la llamada a una función asíncrona
He hecho un montón de lecturas pero no he encontrado una solución que funcione
lo más cercano que he visto está aquí: Exportar el resultado de una función asíncrona en React
por favor ten en cuenta que quiero exportar un objeto, y ese objeto es el resultado de una función asíncrona, NO exportar la definición de la función asíncrona en sí
aquí está mi caso de uso e implementación hasta ahora:
tenemos un archivo llamado config.ts
tradicionalmente, config.ts ha contenido un objeto con configuraciones relevantes de tiempo de ejecución como la exportación por defecto
esto nos permite simplemente
import config from '../config'o lo que seaNuestra gestión de configuración y secretos se ha vuelto más compleja, de manera que necesita hacer varias llamadas a varios repositorios de secretos (AWS, Azure, etc.)
He refactorizado config.ts para que ahora se vea algo así:
export const basicValues = {
color1: 'red'
}
async function buildConfig(){
const valuesOut = {...basicValues}
valuesOut.color2 = await getSecret('color2');
valuesOut.color3 = await getSecret('color3');
return valuesOut;
}
export default buildConfig()
donde getSecret es alguna función que realiza una llamada asíncrona arbitraria
Estoy exportando basicValues arriba porque tengo algunas configuraciones en ellas que son necesarias para hacer las llamadas dentro de getSecret.
Al exportar basicValues de esta manera, puedo obtener los valores con un simple const basicConfig=require('../config').basicValues. De esta forma, podemos seguir gestionando todas las configuraciones divertidas en un archivo limpio, centralizado y probado, pero aún así hacer que los valores estén disponibles para su uso muy temprano y evitar dependencias cíclicas.
en conjunto, esto SE SIENTE como si debería funcionar
He probado muchos otros patrones, pero este se siente más natural e intuitivo de leer
aquí está la parte mala:
import config from '../config'da undefined, conexport default buildConfig()- cambiar la exportación a simplemente
export default basicValuesnos da nuestro objeto de configuración como se esperaba (pero sin los valores asincrónicos poblados, obviamente)
¿Qué estoy haciendo mal exactamente aquí?
feliz de proporcionar más detalles según sea necesario
gracias de antemano
Respuesta #1
por favor ten en cuenta que quiero exportar un objeto, y ese objeto es el resultado de una función asíncrona, NO exportar la definición de la función asíncrona en sí
Esto no es posible. Dado que el valor se obtiene de forma asincrónica, todos los módulos que consumen el valor deben esperar a que la acción asincrónica se complete primero; esto requerirá exportar una Promesa que se resuelva con el valor que deseas.
En nuevas versiones de Node, podrías importar la Promesa y usar await a nivel superior para esperar a que se complete:
import buildConfigProm from '../config';
const config = await buildConfigProm;
Si no estás en Node, await a nivel superior no es compatible. Podrías llamar a .then en la Promise en todos los lugares donde se importe:
buildConfigProm.then((config) => {
// put all the module's code in here
});
Si no te gusta eso, la única alternativa real es usar inyección de dependencias. Haz que tus módulos exporten funciones que tomen el config como parámetro, por ejemplo:
// useConfig.ts
export default (config: Config) => {
console.log('color2', config.color2);
};
De esta manera, lo único que tiene que ser asincrónico es el punto de entrada, que espera a que la Promesa se resuelva, y luego llama a los módulos necesarios con ella:
// index.ts
import buildConfigProm from './config';
import useConfig from './useConfig';
buildConfigProm
.then((config) => {
useConfig(config);
})
.catch(handleErrors);
