Home > database >  Get all JSON responses from array of Promises
Get all JSON responses from array of Promises

Time:12-04

I want to make multiple calls for which I have to wait for the answer, and afterwards I want to group all responses in an array. I've not succeeded to do this.

The res constant in code below still retains the array of promises, not their results. I have no idea what else to try. No other stackoverflow answers have been helpful.

What I've tried:

const getProjectData = async (projectID) => await callAPI(`/projects/${projectID}`);

  const solve = async () => {
    const projects = [];
    currentUserProjectIDs.forEach((project) => {
      projects.push(getProjectData(project));
    });

    console.log("projects", projects);

    const res = await Promise.all(projects);
    console.log("solve res", res);
    return res;
  };

  const res = await solve();
  console.log("res", res);

Below is the result of the last console log:


res [
  Response {
    size: 0,
    timeout: 0,
    [Symbol(Body internals)]: { body: [PassThrough], disturbed: false, error: null },
    [Symbol(Response internals)]: {
      url: 'http://localhost:4000/projects/1',
      status: 200,
      statusText: 'OK',
      headers: [Headers],
      counter: 0
    }
  },
  Response {
    size: 0,
    timeout: 0,
    [Symbol(Body internals)]: { body: [PassThrough], disturbed: false, error: null },
    [Symbol(Response internals)]: {
      url: 'http://localhost:4000/projects/4',
      status: 200,
      statusText: 'OK',
      headers: [Headers],
      counter: 0
    }
  }
]

callAPI function:

export const callAPI = async (path, body, method = "GET") => {
  const config = {
    method: method,
    headers: {
      "Content-Type": "application/json",
    },
  };
  if (body) {
    config.body = JSON.stringify(body);
  }
  const URL = `${process.env.HOST}${path}`;
  return await fetch(URL, config);
};

EDIT: I have tried another way, but still unsuccessful. In the code below, the console.log inside the second .then() logs the correct data, but the returned prj is still an empty array...

const solve = async () => {
    const projects = [];
    currentUserProjectIDs.map((p) => {
      callAPI(`/projects/${p}`)
        .then((r) => {
          return r.json();
        })
        .then((a) => {
          console.log("a", a);
          projects.push(a);
          return a;
        });
    });
    return projects;
  };

  const prj = await solve();
  console.log("prj", prj);

CodePudding user response:

This is a bit cleaner solution based on your first attempt:

export const callAPI = async (path, body, method = 'GET') => {
  const config = {
    method: method,
    headers: {
      'Content-Type': 'application/json'
    }
  }

  if (body) {
    config.body = JSON.stringify(body)
  }

  const URL = `${process.env.HOST}${path}`
  const res = await fetch(URL, config)

  if (!res.ok) throw new Error('Error fetching data')

  return res.json()
}

const getProjectData = (projectID) => callAPI(`/projects/${projectID}`)

const solve = () => {
  const projects = currentUserProjectIDs.map((project) => {
    return getProjectData(project)
  })

  return Promise.all(projects)
}

solve()
  .then((data) => console.log(data))
  .catch((err) => console.error(err))

Let me know if that helps.

CodePudding user response:

Your edit is almost correct, but you have to use the array returned from .map and include the Promise.all from your original post:

const solve = async () => {
   const projects = currentUserProjectIDs.map((p) => {
     return callAPI(`/projects/${p}`)
        .then((r) => {
          return r.json();
        });
    });
    return Promise.all(projects);
  };

  const prj = await solve();
  console.log("prj", prj);

Pushing to a separate array won’t work because the code in .then is executed asynchronously.

You will probably also want to handle errors with .catch, I assume you omitted that for brevity.

CodePudding user response:

To get all JSON responses from an array of promises, you can use the Promise.all() method in JavaScript. The Promise.all() method takes an array of promises as input, and it returns a new promise that is resolved when all of the input promises are resolved.

For example, if you have an array of promises that each return a JSON response, you can use the Promise.all() method to get all of the JSON responses in a single array, like this:

const promises = [
  fetch("http://example.com/api/users").then(response => response.json()),
  fetch("http://example.com/api/posts").then(response => response.json()),
  fetch("http://example.com/api/comments").then(response => response.json())
];

Promise.all(promises).then(responses => {
  // responses is an array of JSON responses
});

In this code, the promises array contains three promises that each fetch a different API endpoint and return the JSON response. The Promise.all() method is used to get all of the JSON responses in a single array. When all of the promises are resolved, the then() method is called and the responses array is passed as an argument. The responses array contains the JSON responses from all of the promises.

Overall, to get all JSON responses from an array of promises, you can use the Promise.all() method in JavaScript. This method allows you to get all of the JSON responses in a single array, which can be useful for working with multiple API responses in your code.

CodePudding user response:

You can do so:

  const getProjectData = async (projectID) => await callAPI(`/projects/${projectID}`);
    
  const solve = async () => {
    const res = await Promise.all(
     currentUserProjectIDs
       .map(id => getProjectData(id)
       .then(res => res.json())
   );
    return res;
  };
  const res = await solve();

CodePudding user response:

You are using too many await in your original code. Since you are pushing all your promise inside Promise.all you don't need another await in the middle.

Remove await from below lines,

return await fetch(URL, config);


const getProjectData = async (projectID) => await
callAPI(`/projects/${projectID}`);

Also, your API URL is this http://localhost:4000 according to your logs, you have to reverify if it's correct.

Other things seem fine. It should work and will be able to get the data.

  • Related