Estoy haciendo algunas llamadas API de una aplicación web. Primero estoy recibiendo los detalles de mi pareja (un grupo de hoteles). Este compañero tiene algunas propiedades. Para cada una de estas propiedades, necesito conseguir sus habitaciones; Luego, para cada una de estas habitaciones, necesito obtener su disponibilidad y reservas. Me gustaría realizar todas estas llamadas de manera asíncrona (es decir, tan pronto como tenga la información de la habitación de una propiedad, puedo obtener sus reservas y disponibilidades, sin esperar a tener los detalles de todas las propiedades). Me gustaría saber cuándo se carga todo. A continuación se muestra un código simplificado utilizando los tiempos de espera para simular las llamadas API.

He intentado empujar cada nueva promesa en una matriz, y usar la promesa. Todo en esta matriz, pero me encuentro con el mismo problema.

También he intentado incrementar un mostrador cada vez que se realiza una consulta, y disminuye el mostrador cada vez que se resuelve; ¿Esto está funcionando pero no parece muy limpio?

        const getPartner = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getPartner finished');
                    resolve({
                        properties: [1, 2, 3],
                    });
                }, 1000);
            });
            return p;
        }

        const getRooms = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getRooms finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            return p;
        }

        const getAvailabilities = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getAvailabilities finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            return p;
        }

        const getBookings = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getBookings finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            return p;
        }

        function main() {
            getPartner().then((partner) => {
                Promise.all([
                    partner.properties.forEach((property) => {
                        getRooms().then((rooms) => {
                            rooms.forEach((room) => {
                                getAvailabilities();
                                getBookings();
                            })
                        });
                    })
                ]).then(() => {
                    console.log('all finished');
                });
            });
        }

        main();

Espero "todo terminado" para mostrar el último en la consola. En su lugar, se muestra inmediatamente después de "GetPartner terminado"

EDITAR: Esto es lo que intenté con un contador:

const promises = [];

        const getPartner = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getPartner finished');
                    resolve({
                        properties: [1, 2, 3],
                    });
                }, 1000);
            });
            promises.push(p);
            return p;
        }

        const getRooms = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getRooms finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            promises.push(p);
            return p;
        }

        const getAvailabilities = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getAvailabilities finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            promises.push(p);
            return p;
        }

        const getBookings = () => {
            const p = new Promise((resolve) => {
                setTimeout(() => {
                    console.log('getBookings finished');
                    resolve([1, 2, 3]);
                }, 1000);
            });
            promises.push(p);
            return p;
        }

        function main() {
            getPartner().then((partner) => {
                partner.properties.map((property) => {
                    getRooms().then((rooms) => {
                        getAvailabilities();
                        getBookings();
                    })
                })
            })
            .then(() => {
                Promise.all(promises).then(() => {
                    console.log('all finished');
                });
            });
        }

        main();
0
Gnub 1 jul. 2019 a las 13:51

1 respuesta

La mejor respuesta

Varios problemas:

  • forEach no devuelve nada, pero debe devolver una matriz: para alimentar a Promise.all.

  • Usar Promise.all en cada caso donde tienes múltiples promesas

  • devolver las promesas siempre que necesite encadenar uno en una devolución de llamada then

Así es como funcionaría:

function main() {
    getPartner().then((partner) => {
        return Promise.all(partner.properties.map((property) => {
            return getRooms().then((rooms) => {
                return Promise.all(rooms.map((room) => {
                    return Promise.all([getAvailabilities(), getBookings()]);
                }))
            });
        })).then(() => {
            console.log('all finished');
        });
    });
}
3
trincot 1 jul. 2019 a las 11:00