[英]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.