卸载组件时中止嵌套的获取请求
Aborting nested fetch requests when component is unmounting
以下函数在使用时获取并 returns 单个 post 的最多 50 条评论的数组。它首先通过 ID 获取单个 post,并且这个 post 对象有一个评论 ID 数组,它将获取这些 ID。
我的目标是在我的 React class 组件中使用 componentWillUnmount
提前中止此任务,方法是在 class 实例的信号上调用 abort
。信号作为 abortSignal
.
传递
问题是,我遇到了嵌套获取请求的情况。我应该如何处理这个问题,以便我可以确保在卸载组件时中止任何正在进行的获取请求?如我所见,如果这个阶段已经完成,将信号传递给外部提取是不够的。我应该在这个函数内部创建另一个信号,然后传递给单独的提取吗?
const fetchComments = async (type, abortSignal) => {
const res = await fetch(endpoints[`${type}Stories`]);
const post = await res.json();
return Promise.all(post.slice(0, 50).map(async id => {
const url = endpoints.singleStory.replace('[id]', id);
const comment = await fetch(url);
return comment.json();
}));
}
我看不出有什么理由不能在所有 fetch
调用中重复使用 abortSignal
。您可能还想在 await
ing 之后检查其 aborted
标志,以便您主动退出:
const fetchComments = async (type, signal) => {
const res = await fetch(endpoints[`${type}Stories`], {signal});
if (signal.aborted) {
return; // Or whatever
}
if (!res.ok) {
throw new Error("HTTP error " + res.status);
}
const post = await res.json();
if (signal.aborted) {
return; // Or whatever
}
return Promise.all(post.slice(0, 50).map(async id => {
// Probably not much point to checking `signal.aborted` here, you *just* checked it above
const url = endpoints.singleStory.replace('[id]', id);
const comment = await fetch(url, {signal});
if (!comment.ok) {
throw new Error("HTTP error " + comment.status);
}
return comment.json();
}));
}
两个注意事项:
- 我把
abortSignal
改成了signal
,这样我就可以在传给fetch
的时候用shorthand属性符号了,因为我很懒。 :-)
- 您的代码正在成为 the
fetch
footgun 的牺牲品 — 您需要检查 HTTP 是否成功,它只会拒绝 网络 错误,而不是 HTTP 错误。我在上面插入了支票。
注意: 如果您可以修改 API,我强烈建议您可以在初始 [=12] 中征求 50 条评论=],或者至少能够请求一批评论,而不是使用自己的 HTTP 请求单独加载每个评论(尽管 HTTP/2 有很大帮助)。
以下函数在使用时获取并 returns 单个 post 的最多 50 条评论的数组。它首先通过 ID 获取单个 post,并且这个 post 对象有一个评论 ID 数组,它将获取这些 ID。
我的目标是在我的 React class 组件中使用 componentWillUnmount
提前中止此任务,方法是在 class 实例的信号上调用 abort
。信号作为 abortSignal
.
问题是,我遇到了嵌套获取请求的情况。我应该如何处理这个问题,以便我可以确保在卸载组件时中止任何正在进行的获取请求?如我所见,如果这个阶段已经完成,将信号传递给外部提取是不够的。我应该在这个函数内部创建另一个信号,然后传递给单独的提取吗?
const fetchComments = async (type, abortSignal) => {
const res = await fetch(endpoints[`${type}Stories`]);
const post = await res.json();
return Promise.all(post.slice(0, 50).map(async id => {
const url = endpoints.singleStory.replace('[id]', id);
const comment = await fetch(url);
return comment.json();
}));
}
我看不出有什么理由不能在所有 fetch
调用中重复使用 abortSignal
。您可能还想在 await
ing 之后检查其 aborted
标志,以便您主动退出:
const fetchComments = async (type, signal) => {
const res = await fetch(endpoints[`${type}Stories`], {signal});
if (signal.aborted) {
return; // Or whatever
}
if (!res.ok) {
throw new Error("HTTP error " + res.status);
}
const post = await res.json();
if (signal.aborted) {
return; // Or whatever
}
return Promise.all(post.slice(0, 50).map(async id => {
// Probably not much point to checking `signal.aborted` here, you *just* checked it above
const url = endpoints.singleStory.replace('[id]', id);
const comment = await fetch(url, {signal});
if (!comment.ok) {
throw new Error("HTTP error " + comment.status);
}
return comment.json();
}));
}
两个注意事项:
- 我把
abortSignal
改成了signal
,这样我就可以在传给fetch
的时候用shorthand属性符号了,因为我很懒。 :-) - 您的代码正在成为 the
fetch
footgun 的牺牲品 — 您需要检查 HTTP 是否成功,它只会拒绝 网络 错误,而不是 HTTP 错误。我在上面插入了支票。
注意: 如果您可以修改 API,我强烈建议您可以在初始 [=12] 中征求 50 条评论=],或者至少能够请求一批评论,而不是使用自己的 HTTP 请求单独加载每个评论(尽管 HTTP/2 有很大帮助)。