我正在为Hacker新闻创建简单的克隆,我想使用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;
答案 0 :(得分:3)
我认为这里有两个问题。
1-您正在等待的函数不是异步函数。您正在执行帖子postsIDsArray.slice(0, 50).map(...)
-它只会解析为一个空数组(您不返回获取)。您可以返回获取,然后有一系列的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,因此您可以在两者之间等待。~~-编辑-删除,让Lione欢呼
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);
}, []);