0

I want to fetch data with API. Fecth is my utils, the get API data. It working the only array so I used the fetch function in the javascript the sample object below. My utils is not supported object.

The problem I'm having is not related to utils. The problem is array push in async function.

Array push is not working the map function outside :(

But, is working in the map function :)

What should I do to run outside?

/* eslint-disable */
import Fetch from '@/utils/fetch';

async function allPosts(req, res) {
  const myPostsAll = await Fetch(`${process.env.NEXT_PUBLIC_API_URL}/${process.env.NEXT_PUBLIC_API_USERNAME}`);

    const posts = [];

    myPostsAll.map(async (item) => {
        const { id } = item;
        const myPostRes = await fetch(`${process.env.API_URL}/${id}`);
        const myPost = await myPostRes.json();

        const { title, description, cover_image, body_html } = myPost;

        posts.push({
            id: id.toString(),
            title,
            thumbnail: cover_image,
            description,
            content: body_html,
        });

        // It's work
        console.log(posts);
    });

    // It's not work
    console.log(posts);
}

  • I have reviewed this, but I don't understand if I need to use `superagent` or not? –  Jun 27 '20 at 11:23
  • I have no idea what `superagent` is. But your code displays a very common misunderstanding of asynchronous code - it's not clear what your aim is but by reading the top answers to the linked question you should get some good ideas. – Robin Zigmond Jun 27 '20 at 11:27
  • You are misusing `.map()` here. `.map()` is for transforming one array into another array. If you just want side-effects, use `for..of`, but there is a way to use `.map()` effectively here. – JLRishe Jun 27 '20 at 11:34

2 Answers2

1

The best way to go about this is to utilize Promise.all:

async function allPosts(req, res) {
    const myPostsAll = await Fetch(`...`);
  
    // use `Array.map` to create an array of
    // `Promise`s, then pass that array as an argument
    // to `Promise.all` which will wait for all 
    // `Promise`s to resolve and return an array of objects
    const posts = await Promise.all(
      myPostsAll.map(async (item) => {
        const { id } = item;
        const myPostRes = await fetch(`${process.env.API_URL}/${id}`);
        const myPost = await myPostRes.json();
        const { title, description, cover_image, body_html } = myPost;

        return {
          id: id.toString(),
          title,
          description,
          thumbnail: cover_image,
          content: body_html,
        }
      })
    );
    console.log(posts);
}

Also, the reason why your current solution doesn't work is because there's nothing in your code that says to wait for myPostsAll to finish before calling console.log(posts) at the end of your function outside of the callback of the Array.map function:

async function test() {
  const posts = [];
  
  // this is asynchronous, so it won't "wait"
  // to finish before moving to the next statement,
  // unless you apply the solution above with `Promise.all`
  // and `await`
  myPostsAll.map(async () => {
    const myPostRes = await fetch(`...`);
    posts.push(...);
  })

  // gets called prior to `myPostsAll.map` completing
  console.log("posts", posts);
}

References:

goto
  • 4,336
  • 15
  • 20
  • I couldn't understand how to use this in async functions. It's worked, thanks for your experiences and help. :) –  Jun 27 '20 at 11:38
  • @YasinATEŞ see the edit for more explanation – goto Jun 27 '20 at 11:40
-1

Try this way:

/* eslint-disable */
import Fetch from '@/utils/fetch';

async function allPosts(req, res) {
  const myPostsAll = await Fetch(`${process.env.NEXT_PUBLIC_API_URL}/${process.env.NEXT_PUBLIC_API_USERNAME}`);

    

    const posts=myPostsAll.map(async (item) => {
        const { id } = item;
        const myPostRes = await fetch(`${process.env.API_URL}/${id}`);
        const myPost = await myPostRes.json();

        const { title, description, cover_image, body_html } = myPost;

        return {
            id: id.toString(),
            title:title,
            thumbnail: cover_image,
            description,
            content: body_html}
        

        
    });



    // It's not work
    console.log(posts);
}

Davide Cavallini
  • 216
  • 4
  • 15