Antes de que todos comiencen a gritar sobre la refactorización y las devoluciones de llamada, lea la pregunta en su totalidad, por favor :)

Tengo la siguiente situación en javascript (código simplificado para mayor comodidad):

    function myFunc(){
        var myItems = getItemsAsync(); //this returns a promise

        return {
            settings: {
                type: "items",
                component: "accordion",
                items: myItems //WRONG! This is a promise, not the data itself!
            }
        }
    }

Aquí está la situación: tengo un marco externo que llama a myFunc y espera que el objeto devuelto {settings: etc...} ya tenga todos los valores completados, incluido el subobjeto items. No tengo control sobre cómo este marco llama a myFunc, por lo que no puedo cambiarlo para aceptar una promesa o un resultado parcial, el objeto devuelto debe estar "listo" cuando myFunc regrese.

Ahora, como puede ver, aquí está el problema: para obtener el items necesito llamar a una API que es asíncrona por diseño y devuelve una promesa. Desafortunadamente, esta API también está fuera de mi control, por lo que no puedo modificarla para que funcione sincrónicamente.

Así que básicamente estoy en un punto muerto: tengo que devolver sincrónicamente un objeto completo, ¡pero una de las piezas de ese objeto solo se puede obtener de forma asincrónica!

¿Hay alguna forma de salir de esto? Todas las preguntas similares que he visto aquí en SO sugieren que no se puede esperar a que se complete una promesa ... ¿es cierto?

Sé lo que estáis deseando decir: "CAMBIA EL CALLER O LA API", pero desafortunadamente ambos son componentes que están totalmente fuera de mi control, ya que son parte de sistemas existentes que NO PUEDO modificar (debido a razones burocráticas, más que técnicas)

¿Alguna idea para salir de esto?

2
Master_T 14 nov. 2017 a las 13:31

2 respuestas

La mejor respuesta

Bueno, por suerte para mí descubrí que el marco que mencioné en mi pregunta (el que llama a myFunc) tiene una fase de inicialización donde puedo inyectar tantas promesas como quiera, y el marco esperará a que se cumplan complete antes de continuar y llamar a las otras cosas, incluido myFunc, por lo que pude construir mi objeto items durante esta fase de inicialización y después de eso estuvo listo para ser utilizado.

Esto resuelve mi problema, aunque no responde a mi pregunta original. Todavía esperaré un par de días para ver si alguien sabe de una solución alternativa, pero por lo que he leído mientras tanto, parece que lo que quiero no se puede hacer.

2
Master_T 14 nov. 2017 a las 13:12

Ya conoces la respuesta :-) Si no tienes otras opciones, no tienes ninguna opción . Es fundamentalmente imposible devolver inmediatamente un valor que se obtendrá en el futuro.

Dicho esto, existen algunas soluciones que pueden detener el mundo de la persona que llama, si puede envolver todo el marco en una fibra o algo similar. Por supuesto, eso requiere un cambio fundamental en todo el sistema, pero se puede hacer sin cambiar el código del marco. Sin embargo, esto podría causar algunos errores debido a una sincronización inesperada.

1
Bergi 14 nov. 2017 a las 13:22