如何等待承诺广告将数据推送到forEach循环中的数组[反应] [英] How to wait promises ad push data to array in forEach loop [react]

查看:51
本文介绍了如何等待承诺广告将数据推送到forEach循环中的数组[反应]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想使用这种效果:

So i want to use this effect:

useEffect(() => {
    return db.collection('users').orderBy('lastName').onSnapshot(snap => {
       const usersArray = []
       snap.forEach( async doc => {
         const user = doc.data()
         if(user.manager) {
            await Promise.all([
            db.collection('users').doc(user.manager).get(),
            db.collection('roles').doc(user.profile).get()
          ]).then(resp => {
                    const manager = resp[0].data()
                    const role = resp[1].data()
                    usersArray.push({
                      id: doc.id,
                      ...user,
                      manager: `${manager.lastName} ${manager.name} ${manager.middleName}`,
                      role: role.profile
                    })
                  })
         } else {
           await db
             .collection('roles')
             .doc(user.profile)
             .get().then(resp => {
              const role = resp.data()
              usersArray.push({
                id: doc.id,
                ...user,
                role: role.profile
              })
             })
         }
         usersArray.push({test: 'test'})
       })
       console.log(usersArray)
       setAgents(usersArray)
     })
   }, [])

这里我要获取用户列表,然后我想为每个用户获取有关他们在系统中及其管理者角色的数据,并更新用户对象并推送到数组.之后,我要渲染它.但是现在,我总是得到空数组.在 console.log 中.然后阻止数据正确.

Here i'm getting list of users, then i want to get for each user data about their role in system and their managers, and update user object and push to array. After that i want to render it. But now, i'm always getting empty array. In console.log of .then blocks data is correct.

请帮助获取正确的代码

推荐答案

这是因为在将任何数据实际写入数组之前,代码的 console.log 部分是同步执行的. forEach 数组属性创建一个与主执行无关的非阻塞回调.如果要确保在执行 console.log 之前先处理 snap 中的每个项目,我建议改用 map ,则map具有唯一的实际返回值的属性(与foreach相反).在这种情况下,返回值将是回调承诺.您可以等待地图的结果以确保所有项目都已写入数组,甚至最好在回调内部返回实际项目.

That is because the console.log part of the code is synchronously executed before any of the data is actually written into the array. forEach array property creates a non blocking callback independent of the main execution. If you want to make sure that every item in snap is processed before executing the console.log I recommend using map instead, map has a unique property of actually returning a value (as opposed to foreach). In this case that return value would be callback promise. You could just await the result of the map to make sure all items were written into the array or even better return the actual items inside of the callback.

这是示例代码(为简单起见,我删除了不需要的 usersArray.push({test:'test'}))

here is example code (for simplicity i removed the usersArray.push({test: 'test'}) which i assume is unneeded)

useEffect(() => {
    return db.collection('users').orderBy('lastName').onSnapshot(snap => {
        const usersArrayPromise = snap.documents.map(doc => {
            const user = doc.data();

            if (user.manager) return Promise.all([
                db.collection('users').doc(user.manager).get(),
                db.collection('roles').doc(user.profile).get()
            ]).then(resp => {
                const manager = resp[0].data();
                const role = resp[1].data();
                return {id: doc.id, ...user, manager: `${manager.lastName} ${manager.name} ${manager.middleName}`, role: role.profile};
            });

            return db.collection('roles')
                .doc(user.profile)
                .get().then(resp => {
                    const role = resp.data();
                    return {id: doc.id, ...user, role: role.profile}
                })
        });
        Promise.all(usersArrayPromise).then(usersArray => {
            console.log(usersArray)
            setAgents(usersArray)
        });
    })
}, []);

请注意以下事实:firebase QuerySnapshot不是实际的数组,而是实现了 forEach 属性之类的数组,如果要使用map,则可以执行 snap.documents.map.

Please take a note of the fact that firebase QuerySnapshot isn't an actual array but implements array like forEach property, if you want to use map you would do snap.documents.map.

这篇关于如何等待承诺广告将数据推送到forEach循环中的数组[反应]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆