我有一个生命周期方法componentDidMount,它调用一个递归异步方法,并且我希望递归函数在获取所有数据后返回一个Promise.
async componentDidMount() {
let response = await fetch(`${STORY_URL}${this.props.match.params.id}.json`);
let result = await response.json();
totalComments = result.descendants;
await this.fetchComments(result.kids, MARGIN);
this.setState({
by: result.by,
time: calculateTimeDifference(result.time)
});
}
而被调用的函数是
async fetchComments(comment, margin) {
return new Promise((resolve, reject) => {
comment.map(async commentId => {
let response = await fetch(`${STORY_URL}${commentId}.json`);
let result = await response.json();
comments.push({
by: result.by,
margin: margin
});
if (comments.length === totalComments + 1) resolve();
if (result.kids !== undefined) this.fetchComments(result.kids, margin * 2);
});
});
}
但是resolve方法不会在setState之前返回至componentDidMount.我通过控制台日志检查.我不知道我在做什么错
解决方法:
您使事情变得过于复杂.使用Promise.all:
async fetchComments(comments, margin) {
// Collect all the results here, otgerwise we would have to flatMap the promises which is more complicated
const result = [];
// Make sure that all comments were processed before returning
await Promise.all( comments.map(async commentId => {
const response = await fetch(`${STORY_URL}${commentId}.json`);
const { kids, by } = await response.json();
if(kids) {
// Get all children and append them to the results, right after the children
const children = await fetchComments(kids, margin * 2);
result.push({ by, margin }, ...children);
} else {
// Otherwise just append this node
result.push({ by, margin });
}
}));
return result;
}
如果顺序很重要,则必须拼合Promise.all的结果:
async fetchComments(comments, margin) {
const result = await Promise.all(comments.map( async commentID => {
const response = await fetch(STORY_URL + commentID + ".json");
const { by, kids } = await response.json();
const result = [{ by, margin }];
if(kids) result.push(... await fetchComments(kids, margin * 2));
return result;
}));
// Flatten the results
return [].concat(...result);
}