17

I'm trying to use node-fetch with nodejs to make api calls to my personal api. I would like to be able to update certain values synchronously within this periodically as things update/change with my database behind the scenes. I know that async and await exist but with all my googling I still don't quite understand them or how they interact with fetch requests.

This is a bit of example code I'm trying to get working but still just logs undefined

const fetch = require('node-fetch');
const url = 'http://example.com';
let logs;

example();
console.log(logs);
async function example(){
    //Do things here
    logs = await retrieveLogs();
    //Do more things here
}

async function retrieveLogs(){
    await fetch(url)
    .then(res => res.json())
    .then(json => {return json})
    .catch(e => console.log(e))
}
Wallace Alley
  • 173
  • 1
  • 1
  • 5
  • 3
    `await example();` – skyboyer Sep 03 '18 at 08:44
  • 3
    `.then(json => {return json})` this line is pointless. Just remove it. – Thomas Sep 03 '18 at 08:51
  • Thanks for the help! Both of those things were somewhat true, but not the whole answer as I still needed to return the fetch like Ali pointed out – Wallace Alley Sep 03 '18 at 09:07
  • 1
    Note that using `async` and `await` does **not** make your action synchronous. It is just syntaxic sugar to make your code more elegant and display it like if it was synchronous. Actions are still asynchrnous behind the scene. – n00dl3 Sep 03 '18 at 09:12

4 Answers4

15

I think you need to return retrieveLogs function result like this:

async function retrieveLogs(){
    return await fetch(url)
    .then(res => res.json())
}
Ali Torki
  • 1,929
  • 16
  • 26
  • 2
    That did it and makes sense as the await is looking for a promise to be resolved. I didn't realize that you could return an await and thought I needed that second .then to actually get the data being returned. I also made a critical error as I think skyboyer was pointing to that I would have to await the original function call (probably with an anonymous function) otherwise that misplaced console.log would fire prior to example() finishing. Thanks! – Wallace Alley Sep 03 '18 at 09:06
  • 1
    Actually upon further inspection it seems I don't need that function to be async and I don't need to await the fetch. I assume the await from the first call in the example() handles that? – Wallace Alley Sep 03 '18 at 09:14
  • Fetch function is a native async function and if you don't wanna to use the await syntax, you can get value by calling **then** after fetching. – Ali Torki Sep 03 '18 at 09:21
  • 4
    Question: "How to sync". Answer: "Here's how to async". Insta-downvote. – Szczepan Hołyszewski May 13 '20 at 13:14
5

As Ali Torki said in comment, fetch() is an async function and cannot be "made" sync no matter what. If you MUST fetch synchronously with HTTP (e.g. because you MUST use it in a property getter which MUSTN'T be async), then you MUST use a different HTTP client, full stop.

Szczepan Hołyszewski
  • 2,707
  • 2
  • 25
  • 39
3
npm install sync-fetch

Synchronous wrapper around the Fetch API. Uses node-fetch under the hood, and for some input-parsing code and test cases too.

https://www.npmjs.com/package/sync-fetch

snez
  • 2,400
  • 23
  • 20
  • YAAS, this is crucial for making top level fetches in node. For example if you are trying to drive a playwright test script. – Robert Moskal Jun 21 '23 at 17:00
0

Using Immediately Invoked Async Function Expression:

(async () => {
  try {

    const response = await fetch('http://example.com')
    const json = await response.json()

  } catch (error) {
    console.log(error);
  }
})();
kuna thana
  • 79
  • 3