Reactjs Async Wait未在useEffect内等待响应

Reactjs Async Wait未在useEffect内等待响应,reactjs,Reactjs,我正在为黑客新闻创建简单的克隆,我想使用useEffect,在它里面我返回ID,然后使用这些ID获得前50篇文章 问题在于fetchHackerNewsPosts中的第二个函数没有等待它在postsArray中添加数据,而是将其打印为空 import React from "react"; import logo from "./logo.svg"; import "./App.css"; function App() { con

我正在为黑客新闻创建简单的克隆,我想使用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;

我认为这里有两个问题

1-您正在等待的函数不是异步函数。你在做postsIDsArray.slice0,50.地图…-这将只解析为一个空数组,而不返回获取。您可以返回fetch,然后您将获得一系列承诺,然后您可以通过Promise等待这些承诺。所有:

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.logpostsArray;尽管如此,因为你不是在等待fetchHackerNewsPosts

可能值得考虑使用all await/async样式或all promise样式,而不是将两者混合使用~~不过,这通常意味着切换到常规循环,而不是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);
  }, []);

我认为这里有两个问题

1-您正在等待的函数不是异步函数。你在做postsIDsArray.slice0,50.地图…-这将只解析为一个空数组,而不返回获取。您可以返回fetch,然后您将获得一系列承诺,然后您可以通过Promise等待这些承诺。所有:

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.logpostsArray;尽管如此,因为你不是在等待fetchHackerNewsPosts

可能值得考虑使用all await/async样式或all promise样式,而不是将两者混合使用~~不过,这通常意味着切换到常规循环,而不是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);
  }, []);

这将帮助你:这将帮助你:因为const postID的postID将花费比承诺更长的时间。但是Promise.all并不限制您使用链接。那么,Promise.allids.mapsync id=>{/*在这里等待内容,然后在完成时返回*/}@lionelrowee-干杯,我没有考虑到这一点!更新答案以包含一个承诺。所有版本的const postID的postID将比promise花费更长的时间。如果有很多帖子,则全部更新。但是Promise.all并不限制您使用链接。那么,Promise.allids.mapsync id=>{/*在这里等待内容,然后在完成时返回*/}@lionelrowee-干杯,我没有考虑到这一点!更新答案,以包含承诺。所有版本