17

I start by saying that I am not 100% sure this is the problem, I mean using await and async.

This is the scenario:

I run this when I first load the page, and works fine, I get the data:

    externalContent(url);

    function externalContent(url) {
      fetch(url)
      .then(res => res.json())
      .then(data => {
        ...cool data...
      });
    }

But then I need to be able to click a button and re run that function with the fetch

So I do

    $(".alm-filters--button").on("click", function() {
      externalContent(url);
    }); 

But when I click, It gives me an error on .then(res => res.json())

The error says: Uncaught (in promise) TypeError: Cannot read property 'then' of undefined

I believe there is an asynchronous issue, I tried, but I do not know enough about using async and await, yet I tried:

    async function externalContent(url) {
      await fetch(url)
      .then(res => res.json())
      .then(data => {
         ...cool data...
      });
    }

But et, I get the same error.

John Vandivier
  • 2,158
  • 1
  • 17
  • 23
rob.m
  • 9,843
  • 19
  • 73
  • 162
  • can you add a `.catch(console.error)` at the end of `fetch`? Is there any error that's caught? – molamk Mar 01 '19 at 19:19
  • Are you really sure that the error happens at `fetch(url).then(res => res.json())` and not at another part of your code? – t.niese Mar 01 '19 at 19:20
  • @t.niese no I am not sure but consoles gives me that line and I everything works – rob.m Mar 01 '19 at 19:21
  • Code seems to be fine. Add the catch at the end of the promise and see if there is an error. – Hemant Parashar Mar 01 '19 at 19:23
  • 1
    If it really happens at that line, then this indicates that you overwrite the `fetch` function with another function, because `fetch(url).then(res => res.json())` should never result in that error, if `fetch` refers to the fetch API of the browser. But I would guess that the problem happens somewhere else. – t.niese Mar 01 '19 at 19:24
  • Possible duplicate of [Fetch API Using Async/Await Return Value Unexpected](https://stackoverflow.com/questions/49661185/fetch-api-using-async-await-return-value-unexpected) – John Vandivier Mar 01 '19 at 19:25
  • @HemantParashar nothing, I get the same error – rob.m Mar 01 '19 at 19:26
  • I think your native `fetch` on window is being overridden by your code. Try this code in another browser or online sandbox.If it works...that's the case – Hemant Parashar Mar 01 '19 at 19:31
  • This looks the same as [your other question](https://stackoverflow.com/q/54949464/215552), but with `async` and `await` added on there to get around being a duplicate... – Heretic Monkey Mar 01 '19 at 20:30
  • @HereticMonkey found the issue, i had another fetch() function defined from an old piece of code. I wanted to delete the other question but couldn't since there was an answer. I have asked to close it. Not cheating. – rob.m Mar 01 '19 at 20:38

2 Answers2

39

Referring to this article should take care of your issue. See the snippet as well.

async function exampleFetch() {
    const response = await fetch('https://reqres.in/api/users/2');
    const json = await response.json();
    console.log(json);
}

exampleFetch()

await substitutes for .then(), so when using await fetch, you don't need to use .then() at all.

Here are a couple other answers which deal with more or less the same issue:

1 - How can I acces the values of my async fetch function? [duplicate]

2 - Fetch API Using Async/Await Return Value Unexpected [duplicate]

John Vandivier
  • 2,158
  • 1
  • 17
  • 23
  • I updated the answer with a comment to clarify. The `const json` should have the same value as what you call `data`. – John Vandivier Mar 01 '19 at 19:12
  • @dvlsg exactly it won't work, even the article he posted says it! You need to use await within an async function – rob.m Mar 01 '19 at 19:14
  • turned it into a snippet, check it out now. yep there was a wrong line previously. – John Vandivier Mar 01 '19 at 19:16
  • check my first part of the code in the question, I don't use await, what am I doing wrong then? – rob.m Mar 01 '19 at 19:18
  • you can't `await` unless you use `async`. Yes, part of the issue is that you are not using an async function/ – John Vandivier Mar 01 '19 at 19:19
  • 1
    Original example doesn't seem wrong to me - in fact, it works when I paste it in my chrome console (or at least gives me the CORS error I expect). Are you sure those lines are the source of the error? – dvlsg Mar 01 '19 at 19:20
  • @JohnVandivier "part" what else? :) – rob.m Mar 01 '19 at 19:20
  • @dvlsg I've been hours on it, the line in console gives me what I say in the question. I really don't get it. Would you come to chat? – rob.m Mar 01 '19 at 19:20
  • @rob.m I don't see you in JavaScript chat? – John Vandivier Mar 01 '19 at 19:28
  • async/await isn't needed for this scenario. It can be used, but it's not going to magically make a call to fetch() that doesn't return anything all of a sudden return something. the problem is elsewhere. – Kevin B Mar 01 '19 at 19:51
  • 100% agree fetch isn't needed here...actually I debugged with him in chat and the fetch function itself was being redefined lmao...but anyway the title is asking how to use it so that's what my answer's about even if it isn't needed – John Vandivier Mar 01 '19 at 20:04
  • 1
    @t.niese we can do it but we don't need to use `.then` even with 1 line of code, for example with parentheses, it is even shorter and we don't need the intermediate variable `res`: `(await fetch("url")).text()` – baptx Mar 31 '22 at 12:44
  • @t.niese in fact there should be 2 `await` if we don't use `.then`: `var result = await (await fetch("url")).json(); console.log(result);`. I am not sure if the 2 `await` were required in the previous Firefox version I tested with. – baptx Jun 02 '22 at 17:16
  • I receive `Promise { }` when I attempt this example in RunJS for the actual return object, despite correct console printing. Same output even if I try and await the function call: `(async() => await exampleFetch())();` – twknab Feb 22 '23 at 06:52
0

my workable fetch pattern

const fetch = require("node-fetch");

async function downloadTxt(url) {
     const response = await fetch(url, {
        mode: 'no-cors',
    })
    return await response.text();
}

(async () => {
     const txt = await downloadTxt("https://dog.ceo/api/breeds/list/all");
     console.log(txt)
})();
Alex
  • 373
  • 1
  • 3
  • 13
  • [Don't forget to handle errors though!](http://blog.niftysnippets.org/2018/06/common-fetch-errors.html) – Bergi Aug 26 '23 at 00:11