Promise all with axios in react native app - javascript

I'm making a react-native weather forecast app. And I'm trying to get all the data using 2 promise all methods
This is the function I call in useEffect
async function getData(){
try{
Promise.all(_.map(savedPlaces, getCurrentWeather)).then((response) => {console.log("current", response.data)})
Promise.all(_.map(savedPlaces, getDailyWeather)).then((response) => {console.log("daily", response.data)})
}
catch(error){
console.log(error)
}
}
The savedPlaces variable is an array with names of the cities I want to get the weather for
And this is one of the two fuctions i use to get the data
const getCurrentWeather = async (places) =>{
const options = {
method: 'GET',
url: 'https://community-open-weather-map.p.rapidapi.com/weather',
params: {q: places.name, lang: 'null', units: 'metric', mode: JSON},
headers: {
'x-rapidapi-host': 'community-open-weather-map.p.rapidapi.com',
'x-rapidapi-key': 'xxx'
}
};
const request = await axios.request(options).then(response => {console.log(response.data)})
return request
}
The other funtion is basicaly the same except little changes in options
And the issu is that I can see the data in print out in this code fragment
.then(response => {console.log(response.data)})
inside the getCurrentWeather functions but when I try to print them out in .then after Promise.all I get undefined, same with the other function.
current [undefined, undefined]
And I'm asking how to properly do it

Here:
const request = await axios.request(options)
.then(response => {console.log(response.data)})
The callback under then prints the data in the console, but has no return statement (returns undefined). Therefore this
return request
returns undefined wrapped in a promise.
Add return response (or return response.data) after the console.log and it should get better.

Related

How can I send data on a get and receive a return?

I have to send this data in a get request but I don't know how to do it. Can you help me?
const ROUTE = "public/v1/route";
export async function showRoute(
flow: string,
token: string
): Promise<RouteParams> {
const response = await client.get(ROUTE);
return response.data;
}
You can use async/await or .then() promise chaining:
import {showRoute} from './path-to-showRoute'
showRoute(/* params */).then(data => sendGetRequest(data))
//or
async function sendRouteInfo(){
const routeData = await showRoute(/* params */)
if (routeData) sendGetRequest(routeData)
}
PS: sendGetRequest is a mock function which simply sends a get request using axios or fetch
axios.get(${URL})
.then(response => console.log(response.data)
.catch(err)=> console.log(err)
That is when you are using axios (npm i axios) then import it
I think what you're looking for is the Fetch-API. For example,
const ROUTE = resourcePath + '?' + new URLSearchParams({ ...params })
fetch(ROUTE) // sends a GET request
.then((res: Response) => res.json() as MyExpectedDataType) // parses JSON response content
.then((data: MyExpectedDataType) => {
// do something with data
})
.catch(err => {
})
// or
async function showRoute(): Promise<Something> {
try {
const res: Response = await fetch(ROUTE)
const data = await res.json() as MyExpectedDataType
// do something with data
}
catch (err) {
}
}
fetch returns a Promise type on which you can chain asynchronous callbacks using .then and handle errors with .catch and .finally. You can also pass request method, headers, body content etc. as an optional second argument to fetch, see the documentation.

How do I nest callbacks for async functions in javascript? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I've looked but haven't been able to find a solution to this specific problem, so I thought I'd ask. I'm a novice javascript developer who clearly needs to read more about scope, callbacks and promises.
I'm trying to nest callbacks to get data out of a http request using the fetch API in javascript. At this point in my project, I've sent data to a node back end, called a few apis, then sent json data back to the client.
I now want to access that data outside of the function getServerData in the below.
I've tried a few different things but haven't been able to figure it out. I feel like I'm missing something obvious.
My current code is below:
//I want to access callback data here
const getServerData = userData => {
// declare data to send
const apiData = userData;
// declare route
const url = 'http://localhost:3030/nodeserver';
// declare POST request options
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(apiData)
};
// Async function to fetch from Node server w/ callback
const fetchUIData = async callback => {
await fetch(url, options)
.then(response => response.json())
.then(data => {
callback(data);
})
.catch(err =>
console.log(
`There was an error fetching from the API POST route:${err}`
)
);
};
// Variable to store callback data
let serverData = [];
// Callback function to use data from fetch
return fetchUIData(data => {
serverData = data;
console.log(serverData);
});
};
You don't nest callbacks when using await. The whole point of await is to get rid of the .then( .then( .then())) callback hell and nesting. Either use .then() (if you enjoy callback hells :) or await; not both together, it doesn't make sense.
const getServerData = async userData => {
const url = 'http://localhost:3030/nodeserver';
const options = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
};
const response = await fetch(url, options);
return response.json()
};
const serverData = await getServerData(userData);
console.log(serverData); // <-- Tadaaa
As soon as the result is based on some asynchronous work, you need to return it using a Promise or a callback.
So const getServerData = userData => { has to either accept a callback, or to return a Promise.
The callback in that part of your code does not seem to have any purpose:
return fetchUIData(data => {
serverData = data;
console.log(serverData);
});
It seems as if you just want to return data from getServerData
So also that part does not make any sense:
.then(data => {
callback(data);
})
So the code could look like this:
const getServerData = userData => {
// declare data to send
const apiData = userData;
// declare route
const url = 'http://localhost:3030/nodeserver';
// declare POST request options
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(apiData)
};
// Async function to fetch from Node server w/ callback
const fetchUIData = () => {
return fetch(url, options)
.then(response => response.json())
.catch(err =>
console.log(
`There was an error fetching from the API POST route:${err}`
)
return null;
);
};
// Callback function to use data from fetch
return fetchUIData()
};
But even that could be simplified:
const getServerData = async userData => {
// declare data to send
const apiData = userData;
// declare route
const url = 'http://localhost:3030/nodeserver';
// declare POST request options
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(apiData)
};
// fetch from Node server
try {
let response = await fetch(url, options)
return response.json()
} catch( err ) {
console.log(
`There was an error fetching from the API POST route:${err}`
)
return null;
}
};
The whole try-catch block is probably also something you want to remove, letting the error propagate. In the current form, the getServerData will always fulfill and only log the error. That's in many cases not what you want. But that depends on the exact use case.
The function is then used that way:
let data = await getServerData();

How can I return multiple function values in a single array

I am crawling 5 different sites for data using node-fetch and cheerio.
everything checks out but I need to collect the returned data from these 5 separate functions in an array.
First I store function name and url for each site in an object like so
url: 'https://sampleurl.com',
crawl: FirstLinkCrawl
}
const secondLink = {
url: 'https://sampleurl.com',
crawl: secondLinkCrawl
}
}```
Then I write the function to crawl each site like so, I ran this function with and without promise, both check out
```const secondLinkCrawl = (body) =>{
return new Promise((res, rej)=>{
"this crawl function is ran here, everything works fine, Data is an object"
const error = false
if(!error){
res(Data)
}else{
rej()
}
})
}```
This here is my fetch function that takes the url and a callback, which is the crawl function
```async function Fetch(url, callback){
const response = await fetch(url)
const html = await response.text()
callback(html)
}
Then I call the fetch and crawl using promise.all() in an attempt to have it return in an array, but in an array,
const promises = [
Fetch(firstLink.url, firstLink.crawl),
Fetch(secondLink.url, secondLink.crawl)]
Promise.all(promises)
.then(values => console.log(values))
.catch(err => console.log(err))
}
When I run this, I get [ undefined, undefined ]
But when I run it without promises and simply log the result, both of them run successfully.
My aim is to get my results in a single array. what can I do?
I also tried declaring an array a the top of the page and then pushing each result into the array, after which I log the array at the bottom of the functions call. But the array returns empty
You're not returning anything from Fetch function that's why it's undefined. You can fix it by -
async function Fetch(url, callback){
const response = await fetch(url)
const html = await response.text()
const result = await callback(html);
return result;
}
As the callback, you are passing in Fetch function returns Promise so we can await it and return the result

How to put a fetch request inside a function and wait for the return value when I call the function

I am using react-native, mongo DB and node js and I need to create some database functions and put them in some modules to be able to reuse them whenever I want. To fetch data from the mongo database, I use the fetch() function which returns a promise. So, for all functions that I created that did not return a value, I used .then and I faced no problems. On the other side, when I return a value inside a fetch().then() function and use this returned value, I get undefined. The code I use for the function looks like:
export const getUsers = () => {
//I cannot use this function because of returning a promise
fetch("http://1jjsd12zaws.ngrok.io/database/", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
})
.then((res) => {
res.json();
})
.then((data) => {
return JSON.stringify(data);
});
};
Then, when I try to run this code:
let users=getUsers();
console.log(users);
It prints undefined.
What I think is going on is that the console.log(users) runs before getUsers() returns its value. But I do not know why does this happen and I want it to wait for getUsers() to execute then, completes its work.
You need to return fetch(..) inside getUsers (that's why you are getting undefined)
You also need to return res.json() inside the first then
Since getUsers returns a Promise, then you need to use .then (or async/await) to access the promise value: getUsers().then(users => {...})
const getUsers = () => {
return fetch('http://1jjsd12zaws.ngrok.io/database/', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(res => {
return res.json();
})
.then(data => {
return JSON.stringify(data);
});
};
getUsers().then(users => console.log(users))
Async and await should cover it. The example on MDN docs explains it better than I can and should apply to your use case.

Function does not wait for fetch request

I am trying to retrieve JSON from a server as an initial state.
But it looks like the function doesn't wait for the response.
I looked at different Stackoverflow posts like How to return return from a promise callback with fetch? but the answers I found didn't seem to help.
// Get the best initial state available
// 1. Check for local storage
// 2. Use hardcoded state with the test value from the server.
export function getInitialState() {
if (localStorage.getItem('Backup') != undefined) {
return returnValue = Map(JSON.parse(localStorage.getItem('Backup')))
} else {
var returnValue = initialState
const GetJSON = (url) => {
let myHeaders = new Headers();
let options = {
method: 'GET',
headers: myHeaders,
mode: 'cors'
};
return fetch(url, options).then(response => response.json());
};
GetJSON('https://example.com/api/v1/endpoint/valid/').then(result => {
// Console.log gives a good result
console.log(result)
// The return is undefined
return returnValue.setIn(['test'], result)
});
}
}
In this case, I receive an undefined while I expect a returnValue JSON where the test property is updated from the server.
So I really want the function getInitialState() to return the state. And to do this it needs to wait for the fetch to finish. I also tried to place return before the GetJSON but this had no effect.
Oke, so I just tried the following:
GetJSON('https://example.com/api/v1/endpoint/valid/').then(result => {
console.log('aaa')
console.log(result)
localstorage.setItem('init', result)
console.log('bbb')
}).then(result => {
console.log('done')
});
This returns aaa and result.
But the localStorage is never set, and the bbb and done are never shown.

Categories

Resources