Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I combine two fetch request into the same array?

I am trying to combine two fetch requests in one call so I can get all the data in the same array.

I have tried the Promise.all method but I don't know if it is the right way to do it.

getWeather = async (e) => {
e.preventDefault();
const city = e.target.elements.city.value;
//const api_call = await
const promises = await Promise.all([
   fetch(`http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&APPID=${API_KEY}`),
  fetch(`http://api.openweathermap.org/data/2.5/forecast?q=${city}&units=metric&APPID=${API_KEY}`)
])

const data = promises.then((results) =>
Promise.all(results.map(r => r.text())))
.then(console.log)

The code actually works and I'm getting data back but I can't understand the json response.

  (2) ["{"coord":{"lon":-5.93,"lat":54.6},"weather":[{"id"…7086601},"id":2655984,"name":"Belfast","cod":200}", "{"cod":"200","message":0.0077,"cnt":40,"list":[{"d…on":-5.9301},"country":"GB","population":274770}}"]

How should I set the state? My state was set like this, with only one call.

  if (city) {
  this.setState({
    temperature: data[0].main.temp,
    city: data[0].name,

Is there a better way to do it?

like image 829
Stranyka Avatar asked May 05 '19 11:05

Stranyka


2 Answers

I'd do:

  getWeather = async (e) => {
   e.preventDefault();

   const fetchText = url => fetch(url).then(r => r.json()); // 1

   const /*2*/[weather, forecast] = /*3*/ await Promise.all([
     fetchText(`.../weather`),
     fetchText(`.../forecast`)
   ]);

   this.setState({ temperature: weather.temp, /*...*/ });
 }

1: By using a small helper, you don't have to call Promise.all twice. With this both requests are done in parallel (and you should use .json() as you want to parse it as JSON).

2: Through array destructuring you can easily get back the promises results.

3: Through awaiting you get the actual benefit from async functions: You don't need nested .then chains

like image 165
Jonas Wilms Avatar answered Oct 06 '22 13:10

Jonas Wilms


You can write in following way which is cleaner approach and will have your data categorised

const success = res => res.ok ? res.json() : Promise.resolve({});

const weather = fetch(`http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&APPID=${API_KEY}`)
.then(success);

const forecast = fetch(`http://api.openweathermap.org/data/2.5/forecast?q=${city}&units=metric&APPID=${API_KEY}`)
.then(success);

return Promise.all([weather, forecast])
.then(([weatherData, forecastData]) => {
const weatherRes = weatherData;
const ForecastRes = forecastData; // you can combine it or use it separately
})
.catch(err => console.error(err));
}
like image 2
arpit sharma Avatar answered Oct 06 '22 12:10

arpit sharma