using a fetch inside another fetch in javascript

There is not an issue with nesting fetch() calls. It depends on what you are trying to achieve by nesting the calls.

You can alternatively use .then() to chain the calls. See also How to structure nested Promises

fetch(url)
.then(function(response) { 
  return response.json()
})
.then(function(data) {   
  // do stuff with `data`, call second `fetch`
  return fetch(data.anotherUrl)
})
.then(function(response) { 
  return response.json(); 
})
.then(function(data) {
  // do stuff with `data`
})
.catch(function(error) { 
  console.log('Requestfailed', error) 
});

I didn't saw an answer with the syntactic sugar of async/await, so I'm posting my answer.

Another way to fetch "inside" another fetch in javascript is like -

try {
    const response = await fetch(url, {method: 'get'});
    const data = response.json();
    //use the data...
    const anotherResponse = await fetch(url, {method: 'get'});
    const anotherdata = anotherResponse.json();
    //use the anotherdata...
 } catch (error) {
    console.log('Request failed', error) ;
 }

So actually you call url after url one by one.

This code will work inside async context.


Fetch returns a promise, and you can chain multiple promises, and use the result of the 1st request in the 2nd request, and so on.

This example uses the SpaceX API to get the info of the latest launch, find the rocket's id, and fetch the rocket's info.

const url = 'https://api.spacexdata.com/v4';

const result = fetch(`${url}/launches/latest`, { method: 'get' })
  .then(response => response.json()) // pass the data as promise to next then block
  .then(data => {
    const rocketId = data.rocket;

    console.log(rocketId, '\n');
  
    return fetch(`${url}/rockets/${rocketId}`); // make a 2nd request and return a promise
  })
  .then(response => response.json())
  .catch(err => {
    console.error('Request failed', err)
  })

// I'm using the result const to show that you can continue to extend the chain from the returned promise
result.then(r => {
  console.log(r.first_stage); // 2nd request result first_stage property
});
.as-console-wrapper { max-height: 100% !important; top: 0; }

This is a common question people get tripped up by when starting with Promises, myself included when I began. However, first...

It's great you're trying to use the new Fetch API, but if I were you I would use a XMLHttpRequest implementation for now, like jQuery AJAX or Backbone's overridden implementation of jQuery's .ajax(), if you're already using these libraries. The reason is because the Fetch API is still so new, and therefore experimental at this stage.

With that said, people definitely do use it, but I won't in my own production code until it's out of "experimental" status.

If you decide to continue using fetch, there is a polyfill available. NOTE: you have to jump through extra hoops to get error handling to work properly, and to receive cookies from the server. If you're already loading jQuery, or using Backbone, just stick with those for now; not completely dreadful, anyway.

Now onto code:

You want a flat structure, else you're missing the point of Promises. It's not wise to nest promises, necessarily, because Promises solve what nested async callbacks (callback hell) could not.

You will save yourself time and energy, and produce less buggy code by simply using a more readable code structure. It's not everything, but it's part of the game, so to speak.

Promises are about making asynchronous code retain most of the lost properties of synchronous code such as flat indentation and one exception channel.

-- Petka Antonov (Bluebird Promise Library)

// run async #1
asyncGetFn()
// first 'then' - execute more async code as an arg, or just accept results
// and do some other ops
.then(response => {
    // ...operate on response data...or pass data onto next promise, if needed
})
// run async #2
.then(asyncGetAnotherFn)
.then(response => {
    // ...operate on response data...or pass data onto next promise, if needed
})
// flat promise chain, followed by 'catch'
// this is sexy error handling for every 'then' above
.catch(err => {  
  console.error('Request failed', err) 
  // ...raise exeption...
  // ... or, retry promise... 
})