首先,我有以下代码部分:
export default class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
try {
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
);
this.Tilte = Result.data.recipe.title;
this.Author = Result.data.recipe.publisher;
this.Image = Result.data.recipe.image_url;
this.Url = Result.data.recipe.source_url;
this.Ingredients = Result.data.recipe.ingredients;
this.PublisherUrl = Result.data.recipe.publisher_url;
this.Rank = Result.data.recipe.social_rank;
} catch (error) {
alert(error);
}
}
CalculateTime() {
try {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
} catch (error) {
console.log(this.RecipeID + ": Length Error->"+error);
}
}
}
然后我将上述代码放在一个单独的文件中,例如:
import Recipe from "./Recipe";
const RecipeController = async () => {
const ID = window.location.hash.replace("#", "");
if (ID) {
AppState.Recipe = new Recipe(ID);
try {
await AppState.Recipe.GetRecipe();
AppState.Recipe.CalculateTime();
console.log(AppState.Recipe);
} catch (error) {
alert(error);
}
}
};
现在,如下图所示,我确实获得了请求的响应并答应了,并且在“成分”数组中有元素,但是有时我仍然收到错误“无法读取未定义的属性'length'当我调用'CalculateTime()'时,尽管现在已经定义了数组,有时我没有收到任何错误,并且工作得很好。为什么这种随机行为呢?甚至JSON响应中的ID和我记录的错误也都匹配,即47746。
答案 0 :(得分:1)
这是为什么有太多try
/ catch
可以掩盖错误原因,使调试困难的原因之一。该问题可以归结为以下内容:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
console.log(Result); // <----- look at this log
this.Tilte = Result.data.recipe.title;
// on the above line, the error is thrown
// Cannot read property 'recipe' of undefined
}
}
const r = new Recipe();
r.GetRecipe();
请参阅日志:您的Result
对象没有.data
属性,因此引用Result.data.recipe
会引发错误。尝试使用Result.recipe
:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
const { recipe } = Result;
this.Tilte = recipe.title;
this.Author = recipe.publisher;
this.Image = recipe.image_url;
this.Url = recipe.source_url;
this.Ingredients = recipe.ingredients;
this.PublisherUrl = recipe.publisher_url;
this.Rank = recipe.social_rank;
}
CalculateTime() {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
console.log('got time', this.Time);
}
}
(async () => {
const r = new Recipe();
await r.GetRecipe();
r.CalculateTime();
})();
除非您实际上可以在特定点处处理错误,否则通常允许该错误向上渗透到调用方,以便调用方可以看到存在错误并进行处理,这通常是很好的。考虑更改原始代码,以便RecipeController
(并且只有RecipeController
)可以看到错误并进行处理-您可以从{{1}中删除try
/ catch
}}。
答案 1 :(得分:0)
您确定某些回复中没有缺少成分吗?而且总是在getRecipe之后调用calculateTime吗?
我将添加条件或后备以防止发生错误,例如。
this.Time = Math.ceil((this.Ingredients || []).length / 3) * 15;
答案 2 :(得分:0)
我推测这种“随机”行为可能与异步代码有关。在计算之前,您需要确保该类具有适当的成分。我有一种感觉,您应该尝试使用.then()
和.catch()
将语法更改为Promise handling,尤其是因为您已经在代码中使用try/catch
了。这种方法将确保在axios请求上正确解决Promise,并消除“随机性”,因为您将更好地控制Promise处理的不同阶段。
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
)
.then((data) => {
this.Tilte = data.data.recipe.title;
this.Author = data.data.recipe.publisher;
this.Image = data.data.recipe.image_url;
this.Url = data.data.recipe.source_url;
this.Ingredients = data.data.recipe.ingredients;
this.PublisherUrl = data.data.recipe.publisher_url;
this.Rank = data.data.recipe.social_rank;
this.Ingerdients = data.data.recipe.ingredient;
}
.catch((err) => {
console.log(err);
return null;
});