getting data from two api using promise.all - javascript

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;
});

Related

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 the result from a fetch function in 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 */);

How to access a value from within a .then promise?

I am doing the following:
fetch("someurl")
.then(data => {return data.json()})
.then(resp => console.log(resp));
Now, usually i do the operations on resp from within the .then function, but would it be possible to assign resp to a variable, or at least store it somewhere so i can retrieve it in another function?
Example:
let thedata;
fetch(URL).then(res => {
return res.json()
}).then(data => {
console.log(data[0].category); //helloWorld
thedata = data[0].category
});
console.log(thedata);
function printsomething()
{return thedata}
Now thedata is going to be undefined, and i can't use the function printsomething without having it inside the .then() function.
This is what i meant by my question.
By assigning the fetch Promise chain to a variable, you can then call .then on that variable from multiple locations, though that's somewhat odd to do:
const prom = fetch("someurl")
.then(res => res.json());
prom.then((data) => {
console.log(data);
});
// Separately:
prom.then((data) => {
console.log(data.foo);
});
In most cases, it would make more sense to use your original strategy of putting everything inside a single .then after res.json().
Sure you can do that - but then you will need to track whether the async function has returned a value, which may be as simple a checking whether the value is defined. The variable could be in global scope, or a field in some object you import. But by not having the code that requires it called from within the then, it means wrapping use of that variable in a check, and handling the possibility it hasn't been set yet. Whether or not that is a good idea depends on context - best to avoid it if you can, but it's a pattern I have used on occasion.
No matter how you handle it you will need to either check or wait for the value so it's best to use it within the .then()
While it can be done if you need the variable outside of the .then() I think async/await is cleaner/easier to manage the flow by awaiting functions till they finish in the same way that .then would and ensuring your variable is available (you should still validate):
const someAPI = "https://jsonplaceholder.typicode.com/todos/1"
let data = null
const fetchFunc = async () =>{
const response = await fetch(someAPI)
data = await response.json()
// use data
}
const asyncFunc = async () => {
await fetchFunc()
console.log(data);
//use data
}
asyncFunc()

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

Promise.all with promise chain inside

I have a method like this:
doSomeRequests(listOfRequestParameters) {
let requests = listOfRequestParameters.map(parmeter => {
return axios.get(url + parmeter)
.then(data => {
const parameters= data.parameters;
return axios.delete(url, parameters)
})
})
return Promise.all(requests);
}
In this function I want to complete API requests for each element in a list (listOfRequestParameters), but for every element in the list I have to do two API requests.
The axios methods both return Promises.
The problem is that I do catch the result of the Promise returned y doSomeRequests method, but if one API requests fail I get an UnhandledPromiseRejectionWarning.
What am I missing? Is there a way to do this kind of Promise chain?
Thanks to #charlietfl for asking me if I really do doSomeRequests(..).then().catch(). Turns out I don't, I accidentally did doSomeRequests(..).then().then() but was somehow convinced the I need to search for the error in the "complex" Promise chain.
Anyway, I am sorry for the useless question, thank you for your help.
You need to make sure the map call returns a list of promises, simplifying with async/await you'll get something along the lines:
async doSomeRequests(listOfRequestParameters) {
return Promise.all(listOfRequestParameters.map(async parmeter => {
const data = await axios.get(url + parameter);
const parameters = data.parameters;
return axios.delete(url, parameters);
}));
}
await doSomeRequests(listOfRequestParameters);

Categories

Resources