3

I have two API-calls chained like so:

let weatherPromise;

if (crds) {
    weatherPromise = mapbox.getLocation(crds)
    .then(locData => darksky.getWeather(crds))
    .then(weatherData => Object.assign(weatherData, {city: locData.city}));
} else if (term) {
    weatherPromise = mapbox.getCoords(term)
    .then(locData => darksky.getWeather(locData.crds));
} else {
    weatherPromise = Promise.reject({error: 'Aborted due to unexpected POST-Body'});
}

weatherPromise.then(weatherData => {
    io.emit('update', weatherData);
    console.log(`Answer sent: ${JSON.stringify(weatherData)}`);
}, reject => {
    io.emit('update', reject);
    console.error(reject.error);
});

But it is not working at all. The error-handling is all over the place (mainly just logging undefined and failing) and for example locData doesn't seem to be accessible in that second then() anymore. I tried nesting Promises and it worked fine but I would like to avoid that anti-pattern if I can.

leonheess
  • 16,068
  • 14
  • 77
  • 112
  • You can use `async/await` along with `try` and `catch` blocks for error handling. – Rohit Kashyap Aug 26 '19 at 20:59
  • @RohitKashyap Why can't I use Promises? – leonheess Aug 26 '19 at 21:00
  • You can, and also nesting promises is not an anti-pattern. This is certainly opinionated. – Rohit Kashyap Aug 26 '19 at 21:01
  • @RohitKashyap Seems to be somewhat agreed on: https://stackoverflow.com/a/25569299/7910454 – leonheess Aug 26 '19 at 21:04
  • 1
    it seems like what you want to do here is _join_ promises, not chain them; consider doing something like `Promise.all([mapbox.getLocation(crds), darksky.getWeather(crds)]).then([locData, weatherData] => ...)` – Hamms Aug 26 '19 at 21:27
  • 1
    It's an antipattern to *use a promise inside of a promise constructor*, but nesting the usage of promises is totally fine and mandatory in some cases. I'd just use `async` / `await` for readability & maintainability though. – Jonas Wilms Aug 26 '19 at 21:30
  • @JonasWilms I'm struggling with implementing `async / await` here. Could you provide an example? In case it is relevant: The code I'm actually working with is [here](https://github.com/MiXT4PE/wthr/blob/master/index.js) starting in line 44. Thank you in advance – leonheess Aug 27 '19 at 21:48

1 Answers1

2

You can nest `.thens´, but in this case, I'd clearly go with async / await:

async function retrieveWeather() {
   if (crds) {
      const locData = await mapbox.getLocation(crds);
      const weatherData = await darksky.getWeather(crds);

      return Object.assign(weatherData, {city: locData.city});
   } else if (term) {
     const locData = await mapbox.getCoords(term);
     const weatherData = await darksky.getWeather(locData.crds);

     return weatherData;
   } else {
     throw {error: 'Aborted due to unexpected POST-Body'};
   }
}

(async function sendWeather() {
  try {
    const weatherData = await retrieveWeather();
    io.emit('update', weatherData);
    console.log(`Answer sent: ${JSON.stringify(weatherData)}`);
  } catch(error) {
     io.emit('update', error);
     console.error(reject.error);
  }
})();
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151