0

I am trying to make my first API call with NodeJS by using node-fetch, however I am getting UNDEFINED as error.

The call works great on my browser link, however with the code below, it returns undefined:

import fetch from 'node-fetch';

const latLongAirports = [{
        "name": "Madrid",
        "iata": "MAD",
        "lat": 40.49565434242003,
        "long": -3.574541319609411,
    },{
        "name": "Los Angeles",
        "iata": "LAX",
        "lat": 33.93771087455066,
        "long": -118.4007447751959,
    },{
        "name": "Mexico City",
        "iata": "MEX",
        "lat": 19.437281814699613,
        "long": -99.06588831304731,}
]

export function getTemperature(iata){
    let data = latLongAirports.find(el => el.iata === iata);
    var url = "http://www.7timer.info/bin/api.pl?lon=" + data.long + "&lat=" + data.lat + "&product=astro&output=json"
    console.log(url);
    async () =>{
        const response = fetch(url);
        const data2 = await response.json();
        console.log(data2);
    }
}

console.log(getTemperature('MEX'));

Any ideas why I am not getting the data?

Kaguei Nakueka
  • 993
  • 2
  • 13
  • 34
  • Does this answer your question? [Why calling react setState method doesn't mutate the state immediately?](https://stackoverflow.com/questions/30782948/why-calling-react-setstate-method-doesnt-mutate-the-state-immediately) – poPaTheGuru Oct 28 '21 at 09:01
  • that `console.log` is run at the same time with your `await response.json()` so will always be undefined – poPaTheGuru Oct 28 '21 at 09:02
  • 1
    `getTemperature` doesn't even have a `return` statement. Also you have constructed a `async ()=>{}` but never invoke it. – Ricky Mo Oct 28 '21 at 09:03
  • 1
    @poPaTheGuru `fetch(url)` and `await response.json()` don't run at all. `console.log is run at the same time with your await response.json()` no, there is no multi-threading. `so will always be undefined` no, it is undefined because there is no `return`, but you could e.g. return a Promise. – t.niese Oct 28 '21 at 09:04
  • Thanks. How to fix it then? – Kaguei Nakueka Oct 28 '21 at 09:04
  • @RickyMo I thought the async is just needed because of the await. Without it I get: Unexpected reserved word (await). – Kaguei Nakueka Oct 28 '21 at 09:07
  • 1
    Learn what [async/await](https://www.w3schools.com/js/js_async.asp) do – Ricky Mo Oct 28 '21 at 09:09
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – jabaa Oct 28 '21 at 09:09
  • 1
    @jabaa - Certainly answers part of it, but there's a lot more going on above than just that. :-) – T.J. Crowder Oct 28 '21 at 14:11
  • Thanks guys! Very appreciated! – Kaguei Nakueka Oct 28 '21 at 14:19

2 Answers2

2
  • getTemperature() missing return statement
  • fetch() not awaited
  • you have constructed an async ()=>{} but never invoke it

Simply make getTemperature() become async and await to it, also await to fetch and return the result.

export async function getTemperature(iata){
    let data = latLongAirports.find(el => el.iata === iata);
    var url = "http://www.7timer.info/bin/api.pl?lon=" + data.long + "&lat=" + data.lat + "&product=astro&output=json"
    console.log(url);
    
    const response = await fetch(url);
    const data2 = await response.json();
    console.log(data2);
    return data2;
}

console.log(await getTemperature('MEX'));
Ricky Mo
  • 6,285
  • 1
  • 14
  • 30
  • 1
    Nice one! Minor nit pick: Should check `response.ok` before calling `response.json`, details in my blog post [here](http://blog.niftysnippets.org/2018/06/common-fetch-errors.html). – T.J. Crowder Oct 28 '21 at 14:12
1

I suggest making the whole getTemperature function an async function. Also use a try ... catch block when await something.

export async function getTemperature(iata) {

  /* ... */
  
  try {
  
    const response = await fetch(url);
    const data2 = await response.json();
    return data2;
  
  } catch (ex) {
  
    throw ex;
  
  }

}

Now your getTemperature function will return a promise as well


// then/catch

getTemperature("MEX").then((result) => {
  console.log(result);
})
.catch((error) => {
  console.log(error.message);
});


// or async/await

( async function () {
  
  try {
    const result = await getTemperature("MEX");
    console.log(result);
  } catch (ex) {
    console.log(ex.message);
  }

})();
  
turbopasi
  • 3,327
  • 2
  • 16
  • 43
  • 1
    *"Also use a try ... catch block when await something."* I strongly recommend **not** doing that. Instead, let the error (rejection) propagate to the caller, except in top-level entry points (event handlers, mostly) where there's nothing useful the error can propagate to. Also, `try { ... } catch (ex) { throw ex; }` is completely pointless anyway. – T.J. Crowder Oct 28 '21 at 14:13
  • I actually believed without the `try ... catch` block inside `getTemperature` the exception will be unhandled and the app crashes - is this not the case ?? Then I learned something thanks ! – turbopasi Oct 28 '21 at 19:23
  • 1
    Right, that's not the case. :-) You're handling the exception (`catch`), but then throwing it again (`throw`), which is effectively the same as not handling it (since you're not doing anything else in the `catch` block, like cleanup). Either way, the function throws an exception (rejects its promise). Allowing a function to throw/reject is fine, you just handle exceptions at a higher level. – T.J. Crowder Oct 29 '21 at 07:37