解决嵌套承诺的问题



以下是我通常使用promise的方式,到目前为止我还没有遇到任何问题。这里的问题是console.log(this.recipe)是未定义的,当我console.log(JSON.stringify(recipes))时,它显示它是一个空数组。这让我相信我没有正确地解决嵌套的承诺。

ngOnInit(): void {
this.recipeService.getAllRecipesByUserId().then((recipes) => {
this.allRecipes = recipes;
this.recipe = this.allRecipes[0];
console.log(this.recipe);
});
}

getAllRecipesByUserId()函数应返回Recipe[]类型的promise

async getAllRecipesByUserId(): Promise<Recipe[]> {
let recipes: Recipe[] = [];
await this.userService.userRecipeIds().then((ids) => {
ids.forEach((id) => {
const q = query(this.recipeCollection, where('id', '==', id));
getDocs(q).then((querySnapshot) => {
querySnapshot.forEach((doc) => {
recipes?.push(doc.data() as Recipe);
});
});
});
});
return recipes;
}

userRecipeIds((:

async userRecipeIds(): Promise<string[]> {
let user: User = new User();
const q = query(
this.userCollection,
where('userId', '==', this.auth.getCurrentUser()?.uid)
);
return await getDocs(q).then((querySnapshot) => {
querySnapshot.forEach((doc) => (user = doc.data() as User));
return user.recipes;
});
}

我在这里正确地解决了承诺吗?

编辑:

我已将userRecipeIds()方法编辑为以下内容:

async userRecipeIds(): Promise<string[]> {
const q = query(
this.userCollection,
where('userId', '==', this.auth.getCurrentUser()?.uid)
);
const docs = await getDocs(q);
const user = docs.docs[0].data() as User;
return user.recipes;
}

然后随后将getAllRecipesByUserId((重构为以下内容:

async getAllRecipesByUserId(): Promise<Recipe[]> {
let recipes: Recipe[] = [];
const userRecipes = await this.userService.userRecipeIds();
userRecipes.forEach(async (recipeId) => {
const q = query(this.recipeCollection, where('id', '==', recipeId));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
recipes.push(doc.data() as Recipe);
});
});
return recipes;
}

我似乎仍然遇到了同样的问题,在ngOnInit()中检查时,数组似乎是空的。

我不完全理解您的代码,但例如,这个片段看起来是错误的。您在数组上迭代,将每个项分配给一个名为user的字段,因此在forEach发生后,字段用户将获得最后一个项的值,因此您称之为最后一个doc

也许整个方法应该看起来更像这样:

async userRecipeIds(): Promise<Recipe[]> {
const q = query(
this.userCollection,
where('userId', '==', this.auth.getCurrentUser()?.uid)
);
const docs = await getDocs(q);
const recipes = docs.map(doc => doc.data());
return recipes;
}

如果我们只想要第一个元素:

async userRecipeIds(): Promise<User> {
const q = query(
this.userCollection,
where('userId', '==', this.auth.getCurrentUser()?.uid)
);
const docs = await getDocs(q);
const user = docs[0].data();
return user;
}

那么其他函数可能就是这样的?:


async getAllRecipesByUserId(): Promise<Recipe[]> {
const recipes: Recipe[] = await this.userService.userRecipeIds();
return recipes;
}

编辑后的问题的答案:当您需要同时解析多个promise时,例如,当promise是从数组的项创建时。您需要异步处理结果。foreach方法并不关心这一点,它将尽快结束,而无需等待内部承诺的结果。您应该使用Promise.all方法。存储所有承诺,并解决所有承诺,生成一系列结果:


async getAllRecipesByUserId(): Promise<Recipe[]> {
const userRecipes = await this.userService.userRecipeIds();
const recipieQueries = userRecipes.map(recipe => {
const q = query(...));
return getDocs(q);
})
const recipes = await Promise.all(allRecipiesPromises);
return recipes;
}

最新更新