7

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?

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

2 Comments

Again, the code works, but I have no idea how to retrieve the data. I thought it should be for example: this.setState({ temperature: weather.main.temp, But I can't get it out. {"coord":{"lon":-5.93,"lat":54.6},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"base":"stations","main":{"temp":8.77,"pressure":1028,"humidity":61,"temp_min":8.33,...
this is because you are parsing the promise using res.text()... if you want to treat it as json object make it res.json()
2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.