我正在React / Redux上构建一个hackernews克隆。
在组件内部,Item.js我调用this.props.fetchItem(this.props.match.params.id);
以下是fetchItem
动作创建者:
export const fetchItem = (id) => {
return dispatch => {
return axios.get(`${ROOT_API_URL}/item/${id}.json`)
.then(response => {
let story = response.data;
let commentIds = response.data.kids; // Story kids
var allComments = [];
let fetchComments = commentIdArray => {
let promiseArray = [];
// 1. Create requests for each commentId
commentIdArray.forEach(commentId => {
promiseArray.push(axios.get(`${ROOT_API_URL}/item/${commentId}.json`));
})
// 2. Make requests to fetch all commentIds
axios.all(promiseArray)
.then(responseArray => {
responseArray.forEach(response => {
let comment = response.data;
allComments.push(comment);
if(comment.kids){
fetchComments(comment.kids);
}else{
return false;
}
})
console.log("allComments: ", allComments);
})
.catch(error => {
console.log("error promise.all: ", error);
})
}
fetchComments(commentIds)
})
.catch(error => {
if(error.response.status === 401){
console.error("Unauthorized");
}else{
console.error("Something went wrong!");
}
})
}
}
基本上,它接收故事的id并获取该故事的评论。这部分也有效。我在扁平阵列中得到了所有评论。
这是问题所在。我必须在fetchItemSuccess
中的某处调用fetchItem
,以便我可以将数据保存到redux。虽然,我不知道有多少评论,我通过他们的子评论递归地提取它们。
那么,我如何知道我已准备好所有评论,然后致电fetchItemSuccess
?
一个故事:https://hacker-news.firebaseio.com/v0/item/8863.json?print=pretty
评论:https://hacker-news.firebaseio.com/v0/item/8952.json?print=pretty
答案 0 :(得分:0)
以下是一个示例,说明您的源的结构可能会更加健全:
const fetchComments = function(commentIdArray) {
const promiseArray = [];
// 1. Create requests for each commentId
commentIdArray.forEach(commentId => {
promiseArray.push(axios.get(`${ROOT_API_URL}/item/${commentId}.json`));
});
let parentCommentsComments = [];
return axois.all(promiseArray).then(responseArray => {
responseArray.forEach(response => {
const comment = response.data;
parentComments.push(comment);
if (comment.kids) {
return fetchComments(comment.kids);
} else {
return [];
}
});
}).then(kidsComments => {
return parentComments.concat(kidsComments);
});
});
export const fetchItem = (id) => {
return dispatch => {
return axios.get(`${ROOT_API_URL}/item/${id}.json`)
.then(response => {
const story = response.data;
const commentIds = response.data.kids; // Story kids
return fetchComments(commentIds);
})
.then(comments => {
// do something with comments?
})
.catch(error => {
if(error.response.status === 401){
console.error("Unauthorized");
}else{
console.error("Something went wrong!");
}
})
}
}
答案 1 :(得分:0)
想通了。
我只需要跟踪异步方法调用。所以,我添加了一个计数变量。如果count为零,则发送一个动作。
export const fetchItem = (id) => {
return dispatch => {
return axios.get(`${ROOT_API_URL}/item/${id}.json`)
.then(response => {
let story = response.data;
let commentIds = response.data.kids; // Story kids
var allComments = [];
var count = 0; // <=== New Line
let fetchComments = (commentIdArray) => {
let promiseArray = [];
count++; // <=== New Line
// 1. Create requests for each commentId
commentIdArray.forEach(commentId => {
promiseArray.push(axios.get(`${ROOT_API_URL}/item/${commentId}.json`));
})
// 2. Make requests to fetch all commentIds
axios.all(promiseArray)
.then(responseArray => {
responseArray.forEach(response => {
let comment = response.data;
allComments.push(comment);
if(comment.kids){
fetchComments(comment.kids);
}else{
return false;
}
})
count--; // <=== New Line
if(count === 0){ // <=== New Line
dispatch( fetchItemSuccess(allComments) );
}
})
.catch(error => {
console.log("error promise.all: ", error);
})
}
fetchComments(commentIds);
})
.catch(error => {
if(error.response.status === 401){
console.error("Unauthorized");
}else{
console.error("Something went wrong!");
}
})
}
}