异步等待不等待 useEffect 内的响应
Posted
技术标签:
【中文标题】异步等待不等待 useEffect 内的响应【英文标题】:Async await is not waiting for response inside useEffect 【发布时间】:2020-12-03 11:42:43 【问题描述】:我正在为 Hacker news 创建简单的克隆,我想使用 useEffect
并在其中返回 id,然后使用这些 id 获取前 50 个帖子。
问题在于fetchHackerNewsPosts
中的第二个函数,它不会等待它在postsArray
中添加数据,而是将其打印为空。
import React from "react";
import logo from "./logo.svg";
import "./App.css";
function App()
const [posts, setPosts] = React.useState([]);
React.useEffect(() =>
let postsArray = [];
async function fetchHackerNewsPosts()
try
// it waits this function
let postsIDsArray = await fetch(
"https://hacker-news.firebaseio.com/v0/topstories.json"
)
.then((res) => res.json())
.then((result) =>
return result;
);
// it doesn't wait this function
await postsIDsArray.slice(0, 50).map((postId) =>
fetch(`https://hacker-news.firebaseio.com/v0/item/$postId.json`)
.then((res) => res.json())
.then((result) =>
postsArray.push(result);
);
);
catch (error)
console.log(error);
fetchHackerNewsPosts();
console.log(postsArray);
, []);
return (
<div className="p-10">
<header className="">
<h1> Hacker news API </h1>
</header>
<div className="bg-blue-600">list</div>
</div>
);
export default App;
【问题讨论】:
这将对您有所帮助:async-await-inside-arraymap 【参考方案1】:我认为这里有两个问题。
1 - 您正在等待的函数不是异步函数。您正在发布postsIDsArray.slice(0, 50).map(...)
- 它只会解析为一个空数组(您不会返回获取)。你可以返回 fetch,然后你会得到一个 promise 数组,然后你可以通过 Promise.all 等待:
await Promise.all(postsIDsArray.slice(0, 50).map((postId) => fetch(`https://hacker-news.firebaseio.com/v0/item/$postId.json`)
.then((res) => res.json())
.then((result) =>
postsArray.push(result);
));
这仍然会在您 console.log(postsArray);
的位置记录一个空数组 - 因为您没有等待 fetchHackerNewsPosts。
可能值得考虑使用全部等待/异步样式或全部承诺样式,而不是将两者混合使用。 ~~然而,这通常意味着切换到常规循环而不是 map/forEach,所以你可以在两者之间等待。~~ - 编辑 - 删除,欢呼莱昂
React.useEffect(() =>
async function fetchHackerNewsPosts()
const posts = [];
try
const postIDsResponse = await fetch(
"https://hacker-news.firebaseio.com/v0/topstories.json"
);
const postIDs = await postIDsResponse.json();
for (const postID of postIDs)
const postResponse = await fetch(`https://hacker-news.firebaseio.com/v0/item/$postId.json`);
const post = await post.json();
posts.push(post);
return posts;
catch (error)
console.log(error);
setPosts(await fetchHackerNewsPosts());
, []);
正如所指出的 - Promise.all 实际上在这里可能会快很多,因为您无需等待前一个请求完成后再触发下一个请求。
React.useEffect(() =>
async function fetchHackerNewsPosts()
try
const postIDsResponse = await fetch(
"https://hacker-news.firebaseio.com/v0/topstories.json"
);
const postIDs = await postIDsResponse.json();
const postRequests = postIDs.map(async postID =>
const postResponse = await fetch(`https://hacker-news.firebaseio.com/v0/item/$postId.json`);
return await post.json();
);
return await Promise.all(postRequests);
catch (error)
console.log(error);
const posts = await fetchHackerNewsPosts();
setPosts(posts);
, []);
【讨论】:
如果有很多帖子,for (const postID of postIDs)
将比Promise.all
花费更长的时间。但是Promise.all
也不限制你链接.then
s:Promise.all(ids.map(async id => /* await stuff here then return when done */ ))
@LionelRowe - 干杯,没想到!更新了答案以包含一个 promise.all 版本以上是关于异步等待不等待 useEffect 内的响应的主要内容,如果未能解决你的问题,请参考以下文章