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

时间:2019-07-01 10:51:47

标签: javascript promise es6-promise

我正在从Web应用程序进行一些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();

我希望“所有完成”显示在控制台的最后。而是在“ getPartner完成”之后立即显示

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

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

1 个答案:

答案 0 :(得分:3)

几个问题:

  • forEach不返回任何内容,但是您应该返回一个数组-馈送给Promise.all

  • 在每个有多个承诺的情况下,在每种情况下都使用Promise.all

  • 返回承诺,只要您需要在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');
        });
    });
}