13

I want to return fetch API result from a function. but I get undefined and that function doesn't return me fetched data :

function func() {
    fetch('https://randomuser.me/api/?results=10')
    .then(response => response.json())
    .then(json => (json.results))
}

let users = func()

console.log(users);
VLAZ
  • 26,331
  • 9
  • 49
  • 67
Mohammad
  • 385
  • 1
  • 4
  • 16

5 Answers5

19

Fetch is asynchronous and returns a promise. There is no way to take the data returned by fetch and access it synchronously. And it can't return users because the function needs to return synchronously but the data for users won't be available. The function returns before Fetch has a response from the url. That's okay, that's how everything is done and it all still works.

The most flexible way to handle this is to just return the promise from the function. Then you can use then() on the result of the promise and do anything you need to do there:

function func(url) {
    return fetch(url)  // return this promise
    .then(response => response.json())
    .then(json => (json.results))
}

func('https://randomuser.me/api/?results=10')
.then(users => console.log(users))  // call `then()` on the returned promise to access users
.catch(err => /* handle errors */)
Mark
  • 90,562
  • 7
  • 108
  • 148
1

An example of fetch can be as follow:

loadJSON('https://randomuser.me/api/?results=10');
async function loadJSON(fname) {
    var response = await fetch(fname)
    var j =  await response.json()
    document.getElementById('jsondemo1').value = j.name
    document.getElementById('jsondemo2').value = j.year
}

Without async and await:

fetch(url).then(response => response.json())
  .then(result => console.log('success:', result))
  .catch(error => console.log('error:', error));
Ullas Hunka
  • 2,119
  • 1
  • 15
  • 28
  • Can I use that result without any functions ?! maybe I want to use that in a constructor method in a class for example – Mohammad Jul 19 '18 at 07:54
  • Updated the answer have a look – Ullas Hunka Jul 19 '18 at 07:55
  • I see, consider it: for example I have a public fetch_data function and I want to use that in all parts of application. sometimes I want to fetch api in functions or outside of functions and I can't use async/await. Do you have any solution ? – Mohammad Jul 19 '18 at 07:58
1

As this call is asynchronous users is undefined when you are logging this as a response has not been received by the server you need to do the following. You can add then to your func call which will then log users when a response has been received.

function func(url) {
    return fetch(url)  // return this promise
    .then(response => response.json())
    .then(json => (json.results))
}

func('https://randomuser.me/api/?results=10')
.then(users => console.log(users))
Paul Fitzgerald
  • 11,770
  • 4
  • 42
  • 54
  • The variable `Users` can be ,oved to the function block, then the assignment can be made, and the function can then return the variable. One less global-ish variable :-) – Nnanyielugo Jul 19 '18 at 08:11
0

It does not seem like you are returning a value in your function. Your function will evaluate to undefined if a value is not returned.

Return the result of your fetch call (ie: json.results), and tell us what happens.

Nnanyielugo
  • 401
  • 4
  • 13
  • this is not the reason why, it is because the response has not been received from the api – Paul Fitzgerald Jul 19 '18 at 08:01
  • I don't think that is the case. `then` is a promise syntax, and the second `then` call executes after the promise has been resolved or rejected, in which case, the error would be forwarded to a catch block. – Nnanyielugo Jul 19 '18 at 08:02
  • I think it is :-) that function is returning a value - there is an implicit return from arrow functions written like this - bit of reading here for you - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions – Paul Fitzgerald Jul 19 '18 at 08:04
  • he can try to log the response of the second then block in the function to try this out. Log the results of the call inside the function. – Nnanyielugo Jul 19 '18 at 08:06
  • Okay, let's try this. Initialize a variable as undefined. Then in the second then block, assign the results of the call to the undefined variable, then return the variable in the main function scope. It just might be a scope problem. – Nnanyielugo Jul 19 '18 at 08:09
  • @Nnanyielugo that doesn't work, the function returns synchronously, so it will return the undefined value before it has been set in the `then()`. – Mark Jul 19 '18 at 08:19
-4

You need to wrap the fetch inside a Promise and resolve it with the json data. Example :

function func(url) {
    return new Promise((resolve, reject) => { 
        fetch(url)  // return this promise
        .then(response => response.json())
        .then(json => resolve((json.results)))
    });
}

func('https://randomuser.me/api/?results=10')
    .then(users => console.log(users))
Faiz
  • 29
  • 2
  • 7
  • 1
    The `then` does already return a `Promise`. It does not have to be wrapped into another `Promise`. Just the `return` needs to be added. – JojOatXGME Nov 23 '18 at 20:59
  • Adding return still returns undefined from the function. To return the data from the function it needs to be wrapped inside the Promise – Faiz Nov 23 '18 at 21:14
  • 1
    [This other answer](https://stackoverflow.com/a/51417352/4967497) works for me. Just click "Run code snippet". – JojOatXGME Nov 23 '18 at 21:24
  • My bad. Can you please undo the down vote? I will delete the answer – Faiz Nov 23 '18 at 21:33
  • Interesting, it seems that I cannot undo the vote as long as the answer is not edited. However, I don't think that this is a problem. Is there actually a reason to remove the vote first? – JojOatXGME Dec 10 '18 at 21:17