【问题标题】:Can an action be dispatched inside the THEN construct of a promise?可以在 promise 的 THEN 构造中调度操作吗?
【发布时间】:2021-04-22 02:22:00
【问题描述】:

以下是一个组件,它映射上下文变量中的对象并呈现它们。

const MyGroups = () => {
    const { myGroups } = useContext(GlobalContext);

    return (
        <div className="my__groups">
            <h1 className="my__groups__heading">My Groups</h1>
            <div className="my__groups__underline"></div>
            <div className="my__groups__grid__container">
                {
                    myGroups.map(({id, data}) => (
                        <GroupCard
                            key={id}
                            name={data.name}
                            image={data.image} 
                        />
                    ))
                }
            </div>
        </div>
    )
}

以下是我的 store 函数,我使用它从 Firebase 获取数据并将操作发送到 Reducer。

function fetchGroupsFromDatabase(id) {
        let myGroups = [];
        db.collection("users").doc(id).get() // Fetch user details with given id 
            .then(doc => {
                doc.data().groupIDs.map(groupID => { // Fetch all group IDs of the user
                    db.collection("groups").doc(groupID).get() // Fetch all the groups 
                        .then(doc => {
                            myGroups.push({id: doc.id, data: doc.data()})
                        })
                })
            })
            .then(() => {
                const action = {
                    type: FETCH_GROUPS_FROM_DATABASE,
                    payload: myGroups
                };
                dispatch(action);
            })
    }

现在,问题是我想要渲染的“GroupCards”没有渲染,尽管我可以在控制台中看到上下文变量在一段时间后被填充。

与 setTimeout() 完美配合

但是,我观察到,如果我在几秒钟后通过 setTimeout 分派我的操作,我的组件会完美呈现,而不是在 THEN 构造中分派操作,如下所示:

function fetchGroupsFromDatabase(id) {
        let myGroups = [];
        db.collection("users").doc(id).get() // Fetch user details with given id 
            .then(doc => {
                doc.data().groupIDs.map(groupID => { // Fetch all group IDs of the user
                    db.collection("groups").doc(groupID).get() // Fetch all the groups 
                        .then(doc => {
                            myGroups.push({id: doc.id, data: doc.data()})
                        })
                })
            })

            setTimeout(() => {
                const action = {
                    type: FETCH_GROUPS_FROM_DATABASE,
                    payload: myGroups
                };
                dispatch(action);
            }, 3000);
    }

恳请您抽出宝贵的时间,为我的问题提供一些解决方案。

非常感谢。

【问题讨论】:

    标签: reactjs firebase redux react-context


    【解决方案1】:

    为了等待所有组 .get() 调用解决并发送结果,请使用 Promise.all

    async function fetchGroupsFromDatabase(id) {
        const doc = await db.collection("users").doc(id).get() // Fetch user details with given id 
        const myGroups = await Promise.all(
            doc.data().groupIDs.map(groupID => // Fetch all group IDs of the user
                db.collection("groups").doc(groupID).get() // Fetch all the groups 
                    .then(doc => ({ id: doc.id, data: doc.data() }))
            )
        );
        const action = {
            type: FETCH_GROUPS_FROM_DATABASE,
            payload: myGroups
        };
        dispatch(action);
    }
    

    【讨论】:

    • 但是你能解释一下如果我在 THEN 内发送我的动作,为什么它不起作用?
    • 你的意思是你问题中的第一个sn-p? .get Promise 需要时间来解决。因此,您在第一个 .then 中发出了一堆异步请求,但由于第一个不返回任何内容,下一个 .then 在请求完成之前立即运行 - 这就是使用 setTimeout 的原因(但使用Promise.all 更好)。
    • 哦,好吧,所以如果 a then 没有返回任何东西,那么链中的下一个 then 会立即执行?
    • 是的,完全正确。只有当您返回一个 Promise 并且该 Promise 需要一些时间来解决时,下一个 .then 才会需要一些时间来运行 - 然后它会等待返回的 Promise 首先解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    • 2019-09-28
    • 2021-01-22
    • 2019-07-03
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多