繁体   English   中英

Promise 在异步 function 内的循环内

[英]Promise inside a loop inside an async function

我正在使用 react 和 firebase 和 redux 开展一个项目,我有一些由用户创建的项目。 我将用户的 id 存储在项目 object 中,以便稍后在我获得要显示的项目时填充用户。

现在我正在尝试获取项目并通过将用户 ID 替换为有关用户的实际信息来修改它们,但我有一个承诺问题。 在我的代码中,我只得到一个空数组,这意味着在我返回最终结果之前修改没有得到解决。

export const getItems = () => {
  return (dispatch, getState, { getFirebase }) => {
    const firestore = getFirebase().firestore();
    const items = [];
    const dbRef = firestore.collection('items').orderBy('createdAt', 'desc').limit(2);

    return dbRef
      .get()
      .then((res) => {
        const firstVisible = res.docs[0];
        const lastVisible = res.docs[res.docs.length - 1];

        async function getData(res) {

/////////////////////////////////////////////// how to finish this code befor jumping to the return line
          await res.forEach((doc) => {
            firestore
              .collection('users')
              .doc(doc.data().owner)
              .get()
              .then((res) => {
                items.push({ ...doc.data(), owner: res.data() });
              });
          });
////////////////////////////////////////////////

          return { docs: items, lastVisible, firstVisible };
        }

        return getData(res);
      })
      .catch((err) => {
        console.log(err);
      });
  };
};

我不完全了解您要做什么,但我建议您安排一些订单以使您的代码易于阅读和使用。

您可以使用for of来管理异步循环。 我建议这样的事情,免责声明,我是在眼睛上做的,可能有一些错误,但你可以明白。

const getAllDocs = function (data) {
    let temp = [];
    data.forEach(function (doc) {
        temp.push(doc.data());
    });
    return { data: temp };
};

const getDoc = snap => (snap.exists ? { data: snap.data() } : {});

export const getItems = () => {
    return async (dispatch, getState, { getFirebase }) => {
        const firestore = getFirebase().firestore();
        const dbRef = firestore.collection('items').orderBy('createdAt', 'desc').limit(2);
        const usersRef = firestore.collection('users');
        let temps = [];

        const { data: items } = await dbRef.get().then(getAllDocs);
        const firstVisible = items[0];
        const lastVisible = items[items.length - 1];

        for (const item of items) {
            const { data: user } = await usersRef.doc(item.owner).get().then(getDoc);
            const owner = {
                /* whatever this means*/
            };
            temps.push({ ...user, owner });
        }

        return { docs: temps, lastVisible, firstVisible };    
    };
};

问题是 Promise 数组本身并不是 Promise - 所以await它将是一个空操作。

如果你想异步加载它们,你可以使用Promise.all来解决这个问题。

const items = await Promise.all(res.map(async (doc) => {
  const res = await firestore.collection('users').doc(doc.data().owner).get();
  return { ...doc.data(), owner: res.data() };
});

否则,您可以按照其他答案中的建议在 for 循环中await

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM