Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Javascript fetch JSON with ES7 Async Await
// Async/Await requirements: Latest Chrome/FF browser or Babel: https://babeljs.io/docs/plugins/transform-async-to-generator/
// Fetch requirements: Latest Chrome/FF browser or Github fetch polyfill: https://github.com/github/fetch
// async function
async function fetchAsync () {
// await response of fetch call
let response = await fetch('https://api.github.com');
// only proceed once promise is resolved
let data = await response.json();
// only proceed once second promise is resolved
return data;
}
// trigger async function
// log response or catch error of fetch promise
fetchAsync()
.then(data => console.log(data))
.catch(reason => console.log(reason.message))
@kjkta
Copy link

kjkta commented May 9, 2017

@michaelnagy or use a fat arrow if you want to be fancy ;)

const fetchAsyncA = async () => 
	await (await fetch('https://api.github.com')).json()

@FilipIlievski
Copy link

FilipIlievski commented Jul 20, 2017

Nice way to handle network requests, keeping everything in separate files:

RequestService.js

class RequestService {

// async function
async getRequest(url){
  let data = await (await (fetch(url)
    .then(res => {
      return res.json()
    })
    .catch(err => {
      console.log('Error: ', err)
    })
  ))
  return data
}
}

export default new RequestService()

NetwrokService.js

import RequestService from './RequestService'

const BASE_URL = "https://api.nytimes.com/svc"
const API_KEY = "?api-key=GET-YOUR-FREE-API-KEY:)"

class NetworkService {

  getArticles(){
    var url = `${BASE_URL}/search/v2/articlesearch.json${API_KEY}`
    return RequestService.getRequest(url)
  }

  getTopStories(){
    var url = `${BASE_URL}/topstories/v2/technology.json${API_KEY}`
    return RequestService.getRequest(url)
  }

}

export default new NetworkService()

ArticlesMain.js

.....
.....
_getDataStories(){
    NetworkService.getTopStories()
      .then(data => {
        console.log('Data:', data)
        this.setState({
          albumList: data.results
        })
      })
  }

  componentDidMount(){
     this._getDataStories()
  }

....
....

@kdichev
Copy link

kdichev commented Jul 27, 2017

@FilipIlievski why do you use promises in the RequestService class?

@rob-balfre
Copy link

rob-balfre commented Sep 10, 2017

@msmfsd is there any need to assign and return data? This works just as well...

async function fetchAsync () {
  const response = await fetch('https://api.github.com');
  return await response.json();
}

@gengns
Copy link

gengns commented Sep 21, 2017

I came up to a similar use of fetch, but how are you dealing with errors?

async function async_fetch(url) {
  let response = await fetch(url)
  if (response.ok) return await response.json()
  throw new Error(response.status)
}

@Clcll
Copy link

Clcll commented Oct 3, 2017

@gengns use try catch
try { let res = await fetch(url) } catch (e) { **_hangele Error here_** }

@halkeand
Copy link

halkeand commented Dec 15, 2017

Thanks for this gist, make me better understand async/await !

@michaelpumo
Copy link

michaelpumo commented Dec 22, 2017

@FilipIlievski Found the Java guy! 👍

@j2is
Copy link

j2is commented Dec 31, 2017

@FilipIlievski I like this solution. is there any reason to have an await inside of an await?

@pacozaa
Copy link

pacozaa commented Jan 5, 2018

@j2is from my understanding

  1. await number 1(the inner one), used to await fetch() function
  2. await number 2(the outter one), used to await res.json() function

Look at @kjkta answer might got you a clearer understanding in my humble opinion

Is that make sense?

Best,

@Tevinthuku
Copy link

Tevinthuku commented Mar 29, 2018

if You have 2 fetch calls, its better to await the value as compared to the fetch calls themselves, because we will then let the process occur in parallel other than in sequence
like so

   async function bestFetch() {
     const first = fetch();
    const two = fetch();
    const firstvalue = await first.json();
    const secondvalue = await two.json();
  }

Unlike the following ( below ) where the requests will happen in sequence
The second resource will only be fetched once the first request has been resolved

async function badFetch() {
     const first = await  fetch();
    const two = await  fetch();
    const firstvalue = await first.json();
    const secondvalue = await two.json();}

@Dimon70007
Copy link

Dimon70007 commented Apr 17, 2018

thanks @Tevinthuku. The first example is awesome.

@aminnairi
Copy link

aminnairi commented May 11, 2018

Example that can be easily tested with JSONPlaceholder :

(async () => {
  'use strict';
  console.clear();
  const getUser = async identifier => await (await fetch(`https://jsonplaceholder.typicode.com/users/${identifier}`)).json();
  try {
    const firstUser = await getUser(1);
    console.log(firstUser);
    const secondUser = await getUser(2);
    console.log(secondUser);
    // there are 10 users in JSONPlaceholder/Users
  } catch (exception) {
    console.error(`Failed to retrieve user informations: (${exception})`);
  }
})();

@ortonomy
Copy link

ortonomy commented Jul 5, 2018

@gengns gets it.

@senner007
Copy link

senner007 commented Oct 19, 2018

You don't need to await the json. Just return it

async function fetchAsync () {
let response = await fetch('https://api.github.com');
return response.json();
}

Or this:

async function fetchAsync () {
return (await fetch('https://api.github.com')).json();
}

@DiegoRBaquero
Copy link

DiegoRBaquero commented Nov 8, 2018

You should never return await, just return the promise itself return result.json() as @senner007 says.

@longtimehorn63
Copy link

longtimehorn63 commented Nov 15, 2018

This is a little confusing. In my testing if you call fetchAsync() from a non async method it doesn't wait. For example if the testFetch method below is called, the "after fetch()" is logged before the "data retrieved is logged". Am I missing something?? Please tell me I am!!! The only way I have seen it work as expected is when the fetchAsync method is called from a ngOnInit method that is also changed to async.

pubic testFetch() {
console.log('before fetch()');
fetchAsync();
console.log('after fetch()');
}

async function fetchAsync () {
// await response of fetch call
let response = await fetch('https://api.github.com');
// only proceed once promise is resolved
let data = await response.json();
// only proceed once second promise is resolved
console.log('data retrieved');
return data;
}

Ideally I want the json file loaded BEFORE execution continues like implied.

@jagretz
Copy link

jagretz commented Nov 16, 2018

You should never return await, just return the promise itself return result.json() as @senner007 says.

That isn't very informative. Can you please explain why? I haven't directly used the async/await before. The fetch API documentation on MDN states that fetch returns a Promise, and also, that async implicitly returns a Promise

@jagretz
Copy link

jagretz commented Nov 16, 2018

You should never return await, just return the promise itself return result.json() as @senner007 says.

That isn't very informative. Can you please explain why? I haven't directly used the async/await before...

Nevermind, I understand now. The fetch is async, the json method is sync. But in regards to that, I disagree with you comment that you should "never" return an await. If you wrap the fetch call in another function, you can abstract the call and have the calling code be responsible for accessing the response, may it be json, a blob, or something else. If, as you stated, you explicitly return the result by calling json(), that will fail unless the result is json.

@atwright147
Copy link

atwright147 commented May 1, 2019

@jagretz If you return await you are returning a promise anyway (e.g. you will still have to resolve that promise wherever you use the returned "value"). The issue with this is that you have still made the code synchronous (and therefore slower) for no gain.

More info: https://eslint.org/docs/rules/no-return-await

Pertinent quote:

Inside an async function, return await is seldom useful. Since the return value of an async function is always wrapped in Promise.resolve, return await doesn’t actually do anything except add extra time before the overarching Promise resolves or rejects. The only valid exception is if return await is used in a try/catch statement to catch errors from another Promise-based function.

@jagretz
Copy link

jagretz commented May 3, 2019

Learned something new and useful today. Thanks for posting @atwright147 !

@ArcerionDev
Copy link

ArcerionDev commented Jun 10, 2020

How would you change the script to put the output into a variable?

@msawangwan
Copy link

msawangwan commented Jun 11, 2020

How would you change the script to put the output into a variable?

use a closure.

@imbingz
Copy link

imbingz commented Nov 18, 2020

I came up to a similar use of fetch, but how are you dealing with errors?

async function async_fetch(url) {
  let response = await fetch(url)
  if (response.ok) return await response.json()
  throw new Error(response.status)
}

In addition to use try .... catch blocks, it is better to put the above code (by @gengns) inside the try block because "The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing." (quoted from https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)

@gkc-to-public
Copy link

gkc-to-public commented Dec 8, 2020

can u please tell me how to solve this

./src/useGoogleSearch.js
SyntaxError: /media/g/g-c/src/useGoogleSearch.js: Unterminated string constant (11:8)

9 | const fetchData = async () => {
10 | fetch(

11 | 'https://www.googleapis.com/customsearch/v1?key=$
| ^
12 | {API_KEY}&cx=${CONTEXT_KEY}&q=${term}'
13 | )
14 | .then(response => response.json())

@nataliecardot
Copy link

nataliecardot commented Mar 7, 2021

@michaelnagy or use a fat arrow if you want to be fancy ;)

const fetchAsyncA = async () => 
	await (await fetch('https://api.github.com')).json()

As far as I can tell it's not possible to use the returned data in this case. Let me know if I'm missing something.

@Benwebdev
Copy link

Benwebdev commented Sep 29, 2021

Even more fancy :)

import fetch from 'node-fetch'

export default async (...args) => await fetch(...args)

@andreaskuhl
Copy link

andreaskuhl commented Jan 5, 2022

I want to execute a synchronous json fetch call. The following code (see below). It works in principle, but not in the expected order (not synchronously, but asynchronously again).
My log expectation is 1 2 3 4 5 6 7, but I get 1 2 3 7 4 5 6
How do I meet my expectation?

console.log("1 start");

async function fetchInfo() {
    let url = `https://reqres.in/api/products/3`; // only for test
    console.log("  3 fetch");
    let response = await fetch(url);
    console.log("  4 response");
    let data = await response.json()
    console.log("  5 return");
    return data;
}

console.log("2 call fetchInfo()")

fetchInfo()
    .then(data => console.log("6 response object: ...", data));

console.log("7 end / more code ...");

@Proplayz22
Copy link

Proplayz22 commented May 12, 2022

// Async/Await requirements: Latest Chrome/FF browser or Babel: https://babeljs.io/docs/plugins/transform-async-to-generator/
// Fetch requirements: Latest Chrome/FF browser or Github fetch polyfill: https://github.com/github/fetch

// async function
async function fetchAsync () {
// await response of fetch call
let response = await fetch('https://api.github.com');
// only proceed once promise is resolved
let data = await response.json();
// only proceed once second promise is resolved
return data;
}

// trigger async function
// log response or catch error of fetch promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment