Getting the result from a fetch function in javascript - javascript

I'm struggling to get the actual result data from an http fetch in js. I can do it using XMLHttpRequest, but I'd much rather use fetching. I've been trying to get the results from a fetch request like this: fetch('https://api.website.net/?);
I know that you need to assign a then function but nothing I have tried has worked I keep getting more promise objects and no results. I understand vaguely that you need to assign a .then function for once it resolves but I really cannot figure out how to do that.
(This is in browser js not node)

I think that you're getting confused with promises. The fetch function returns a promise and not the data.
I recommend that you read this modern tutorial: https://javascript.info/fetch
This is a very trivial function that gets the url and returns the response data in json:
async function callApi(url) {
const response = await fetch(url);
const data = await response.json();
return data;
}
let data = await callApi('https://api.website.net/?');
// do whatever you want with the data
When dealing with primises there are 2 syntaxes, the old .then() and the new async/await. Using async/await is better, in general, so I recommend using the async/await syntax. With .then() it would look like this:
// Not recommended alternative
fetch('https://api.website.net/?')
.then(response => response.json())
.then(data => {
// do whatever you want with the data
});

Try this:
fetch(....)
.then(response => response.json())
.then(data => /* use data */);

Related

is there a way for a function to return a JSON from a url instead of printing it Fetch API? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 24 days ago.
I want a function that returns a json from a given url using the fetch api (and also if you have a better API option, please tell me, because I'm still learning about promises and etc.)
What I tried:
// [1] with await, I couldn't return, just print on the console
// what needs to change to be able to return instead of printing???
function displayJson1(url) {
async function getJsonPromise(url) {
const response = await fetch(url);
const promise = response.json(); // should i put an await here?? the result was the same
return promise;
}
const promise = getJsonPromise(url);
promise.then((data) => console.log(data));
}
// [2] with .then, I couldn't return, just print on the console
// what needs to change to be able to return instead of printing???
function displayJson2(url) {
const fetchPromise = fetch(url);
fetchPromise
.then((response) => response.json())
.then((data) => console.log(data))
}
in both cases I tried replacing
console.log(data)
by
let json;
json = data;
return json;
But for some reason it didn't work, if you could also explain to me why json = data didn't work I would be grateful.
What i expected/wanted to happen: return the JSON (with the fetch API, using then or await, and if you can show me how I can make the 2 functions return a JSON with both syntaxes it would be even better to learn!)
what actually resulted: both functions, displayJson1 and displayJson2 are printing the JSON (when in fact I just wanted to return the JSON)
in short, instead of displayJson1 and displayJson2 functions I want getJson1 (using await) and getJson2 (using .then) functions
Just write the one function, you dont need to write two functions.
async function getJsonPromise(url) {
const response = await fetch(url);
return response.json();
}
and when you call function just call it like given below.
getJsonPromise().then((response)=>{
console.log("Data: ",response.data)
})

How to convert await data into single array?

I have this code, wherein i'd like to make it in single array.
The output that data produce, is like this:
connections.elements.map((val: any) => {
const url = 'link'
return new Promise((resolve) => {
axios.post(url, val.firstName).then((res: { data: any }) => {
resolve(searchRequestBuilder(res.data.AllResults));
});
});
});
const searchRequestBuilder = async (data: any) => {
console.log(await data);
// for await (let resolvedPromise of data) {
// console.log(resolvedPromise);
// }
};
What I'd like to do is like this:
I already tried to make a variable and use .push, but it still doesn't combine in a single array. What was the thing I am missing?
So since your .map function will return an array of promises, you can store that in a variable, and you can use Promise.all or Promise.allSettled to wait for all the apis to resolve and you can get all the results in a single array in the order that it is requested.
Not part of the question, another thing is if you are not careful, and use await on each api request, it can make a waterfall pattern of requests, which means it will wait for API 1 to finish, then API 2 to finish.
But the way its written here, it will make all the requests parallely, so this will request all the APIs together, and once the last one gets resolved the Promise.all or allSettled will trigger its callback.
const searchRequestBuilder = async (data: any) => {
console.log(await data);
}
async function makeAPIrequests(){
let arrrayOfPromises = connections.elements.map((val: any) => {
const url = 'link'
return new Promise((resolve) => {
axios.post(url, val.firstName).then((res: { data: any }) => {
resolve(searchRequestBuilder(res.data.AllResults));
});
});
});
Promise.allSettled(arrrayOfPromises).
then((results) => console.log(results))
}
Edit:
Also in addition to this, I do not think that you need to return a new Promise inside the map funciton, if you just return axios it should work, since axios itself will return a promise.
The main problem there could be you are making a new call per each item of your elements array. This may create performance issues. The best practice may be to do only one async call and then get all items.
Anyway, if for some reason you really need to make all these ajax calls. Think you are working with asynchronous code, then you really don't know when all calls are answered. To fix this, you need to call your searchRequestBuilder after had made all calls.
I suggest you use Promise.all method.
I left you this link to show you how it works. Basically what you need to do is save all axios.post promises in an array and after loop your elements array call Promises.all passing the array with your promises, then you will be able to execute your searchRequestBuilder without problems.
You can try using .concat:
let allData = [];
allData = allData.concat(await data);

getting data from two api using promise.all

I would like to get data from two API. in the firest call (getDatafromGeonames) I want to get latitude and longitude then I want to pass them as parameters to the second call (getWaetherData) to get weather information then I want to store the result and pass to my endpoint
Here is my try:
const res1 = getDatafromGeonames(geonameAPIURL,city,geonamesKey).then(res =>{
getWaetherData(res.address.lat, res.address.lng)})
Promise.all([res1]).then((res)=>{
//do somthing
console.log(res);
})
a screenshot of the result:
I don't know why it is jumping to then and printing Undefined before it is executing getWaetherData? How can I get data from the first API then use these data to get weather info then do something with these data
thanks a lot :)
Promise.all(promises[]) method is meant to execute some logic when all promises[] has been executed. This would be helpful if you have 2 independant async calls and you want to do something after both of them has been executed.
By what you have described, seems that the second API call you have to do needs the result of the first API call, so the promise operator you should use is .then().
const waetherData = getDatafromGeonames(geonameAPIURL,city,geonamesKey)
.then(res => getWaetherData(res.address.lat, res.address.lng))
or, in EMS6 style:
const getWaetherData = async (geonameAPIURL, city, geonamesKey) => {
const geodata = await getDatafromGeonames(geonameAPIURL,city,geonamesKey);
return await getWaetherData(geodata.address.lat, geodata.address.lng)
}
I have put this last code into a method because if you want to use await operator you need to be in a async context.
Promise.all only works for Promises you can run in parallel, you have to run them in sequence instead:
getDataFromGeonames(geonameAPIURL, city, geonamesKey)
.then((res) => getWeatherData(res.address.lat, res.address.lng))
.then((res) => {
// do something
console.log(res);
return res;
});

Javascript two api calls

Basically I want to call an API twice, make an array [res1, res2] of the two responses, and then operate on this array. My code goes something like that:
function f() {
apiCall1(params1)
.then(response1 => [response1, apiCall2(params2)])
.then(data => someFunction(data))
}
Unfortunately, this method does not work. I get undefined properties of data[0] and data[1]. However, if I make only one API call, everything works fine. I am wondering whether my syntax is wrong and also what would be a good way to implement this? Thanks.
You can group promises with Promise.all, for example:
function f() {
Promise.all([apiCall1(params1), apiCall2(params2)])
.then(data => {
const response1 = data[0];
const response2 = data[1];
})
}
cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Can I somehow get the fetch response in the first `then`?

I am trying to use the Fetch API. It seems from examples that a GET request needs one then to parse the response somehow.
Currently I am doing this
fetch(url)
.then(response => response.json())
.then(response => {
console.log(response);
});
However that first then seems like a boilerplate. I tried to avoid it, for example:
fetch(url)
.then(response => {
console.log(response.json());
});
But this logs me a pending Promise with status resolved.
I read other questions on this topic and read a bit about promises, but I couldn't understand if it's possible to combine it in a single then (if so - how?) or not.
For example, two of the answers here point out that
There is no need to use more than one '.then'
and
there is no good reason to have two .then() handlers as the code from each could have been combined into a single .then() handler
But I couldn't get that example to actually work - I still got a promise :)
On the contrary, the accepted anwser here explains that .then actually does something to the result (extracts the returned from promise), but I couldn't unserstand if I can somehow do that myself, say response.json().then() or response.json().getVal() or is the double-then syntax the only way.
It's quite simple: when you dispatch the a fetch() request, it returns a promise containing the response. That is resolved by the first .then(). Resolving this first promise actually returns Response.
Now this is the tricky part: the methods that read the body of the response, be it .json(), .text(), .blob().... all return promises. This means that you will need to resolve the second promise in order to get the parsed response.
The flow looks like this:
Make a fetch() request, and it returns a Promise of type Response
When you attempt to resolve the content of the Response, it will return a second Promise, whose type depends on the method you use (e.g. .json() returns an object, .text() returns string, .blob() returns Blob).
Resolve the second Promise, and you get your actual parsed response body
p/s: If you're not using fetch() in a top-level context (as of the time of writing top-level await is still not a thing), then you can use async/await to make your code a little more readable:
const response = await fetch(url);
const content = await response.json();
console.log(content);
The first promise returned by fetch can be useful in some cases. If you want to avoid boilerplate, you could simply create your own function:
function fetch_json(url, opts) {
return fetch(url, opts)
.then(resp => resp.json());
}
fetch_json(your_url)
.then(json => console.log(json));
These days I am using the async/await syntax which is the same thing, but looks less like a boilerplate to me.
const response = await fetch(url)
const data = await response.json()
console.log(data)

Categories

Resources