嵌套的异步承诺:如何知道它们何时全部解决?

Nested, asynchronous promises: how to know when they're all resolved?

我正在通过网络应用进行一些 api 调用。首先,我要获取合作伙伴的详细信息(一组酒店)。这个合作伙伴有一些属性。对于这些属性中的每一个,我都需要得到它们的房间;然后对于这些房间中的每一个,我需要获得他们的可用性和预订。 我想异步执行所有这些调用(即,一旦我获得 属性 的房间信息,我就可以获得他们的预订和可用性,而无需等待所有属性的详细信息)。 我想知道何时加载所有内容。下面是使用超时模拟 api 调用的简化代码。

我试图将每个新承诺推送到一个数组中,并在此数组上使用 Promise.all,但我 运行 遇到了同样的问题。

我也试过在每次查询时增加一个计数器,并在每次解决一个问题时减少计数器;这是可行的,但看起来不是很干净?

        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();

我希望 "all finished" 最后显示在控制台中。相反,它会在 "getPartner finished"

之后立即显示

编辑:这是我用计数器尝试过的:

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();

几个问题:

  • forEach 没有 return 任何东西,但你应该 return 一个数组 -- 以提供给 Promise.all.

  • 每个你有多个承诺的情况下使用Promise.all

  • Return 当你需要在 then 回调中链接一个承诺时

这是它的工作原理:

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');
        });
    });
}