Why is async() not returning the fetched data?
Published: 2021-07-07 07:15:40

## Problem:
### I tested my `async` function that fetch data from a url, it works correctly. But it doesn't return the fetched data, why?

Consider a simple example in code-block-1 that fetch an array from `url`. 

```
// code-block-1
// App.js 
const url = "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"

const getData = async () => {
  const response = await fetch(url);
  const quotes = await response.json();
  console.log(quotes);
  return quotes
}
```
`console.log(quotes)` is to check if `quotes` array is fetched from the `url` as expected.

![fetchProblem1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1625567322834/3JmPwh1f8.png)

After checking the console (shown as image above), I am confident that my simple `getData()` works. In order to keep my code clean in `App.js`, I transfer the above code to a separated module `getData.js`.

Updated `getData.js` and `App.js` are as in code-block-2 and code-block-3:

```
// code-block-2
// getData.js 
const url = "https://gist.githubusercontent.com/camperbot/5a022b72e96c4c9585c32bf6a75f62d9/raw/e3c6895ce42069f0ee7e991229064f167fe8ccdc/quotes.json"

const getData = async () => {
  const response = await fetch(url);
  const quotes = await response.json();
  return quotes
}
```

```
//code-block-3
// App.js 
import getData from "./getData";

const quotes = getData()
console.log(quotes)
```
So `quotes` in code-block-3 should contain the array returned by the `fetch()` request, shouldn't it?
Let's check the console.

![fetchProblem2.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1625568958006/jtg31SQdAK.png)

**Huh? How comes it's a `Promise` object???**

## Why did it happen? 
### Gotcha #1

`getData()` is an async function, and **every async function returns a Promise object.**

So the gotcha here is:
- in code-block-1, console logging the `quotes` shows an array of data is correctly fetched.
- since `getData()` returns `quotes`, I *should* get fetched array in code-block-3.

BUT, because it's an async function, it returns a Promise object instead of the fetched array as expected.

So where is the fetched array, and what's the solution?

## Solution

When we dig deeper into the Promise object, here's what we see:

![fetchProblem3.jpg](https://cdn.hashnode.com/res/hashnode/image/upload/v1625580241614/zg4mMXXR3.jpeg)

Indeed the `quotes` array was fetched as shown in the orange box above. How do we access it?
Because `getData()` returns a Promise, we can use `.then()` to access the fetched data from the Promise object.

```
// code-block-4
// App.js
import getData from "./getData";

getData().then((data) => {
  var quotes = data.quotes;
});
```
In code-block-4, the fetched array is assigned to a global variable `quotes`. Note that in this example, `const` and `let` do not work because they define variables in "block scope", which means variables defined by `const` and `let` do not exist outside the block scope.

Or if you are using React, you can assign the fetched array to a state variable:

```
// code-block-5
// App.js
import { useState } from "react";
import getData from "./getData";

const [quotes, setQuotes] = useState([]);

getData().then((data) => {
  setQuotes(data.quotes);
});
```
In code-block-5, the fetched `quotes` array is assigned to the state variable `quotes` via `setQuotes()`. 

The key here is, **whatever you want to do with the fetched data, do it inside callback function within the `.then()` block**. Ok, but why?

### Gotcha #2

It's tempting to think of assigning the result of `.then()` to a variable, like in code-block-6 below:

```
// code-block-6
// App.js
import getData from "./getData";

const quotes = getData().then((data) => data.quotes)
console.log(quotes)
```
This time `quotes` variable should contain the fetched array is it? You guessed it, the answer is no...


![fetchProblem4.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1625572988250/AIRLeQHsU.png)

The above picture shows, we are getting a Promise object, AGAIN!!!! What happened?

It is because the return value of a `.then()` call is again a Promise object. So we are back to square 1.

## Summary

- Both async function and `.then()` return a Promise object which contains the fetched data, INSTEAD OF returning the fetched data itself.
- Access the data and do something with it within the `.then()` callback function as shown in code-block-4 and code-block-5 above.

## Further readings:
- https://stackoverflow.com/questions/43422932/async-await-always-returns-promise
- https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call
- https://stackoverflow.com/questions/34094806/return-from-a-promise-then