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.