Making multiple API requests

I want to make multiple API requests and I am having trouble figuring out how to do it. I have found a few examples online that use JS Promise.all(). Requests that I am trying to make are going to the same domain and are returning different data and since Promise. all() is returning an array of promises I am not sure how to process this since each object will be different and have different properties.

I was able to make all these requests when I am making one request at a time.

Do the requests depend on each other, i.e., does the content of one request depend on the response of an earlier request?

Don’t understand your problem. What is the difference between one request by a time and multiple requests? At the end you have to wait for the request to be done. If this is one or 100 should not make a difference.

ok maybe I am overthinking this. Can you maybe show me a pseudo-code example of how would you process this taking into consideration returned data might is not same with every request

I assume this thread is about the fetch API.

MDN gives this example (here):

fetch('http://example.com/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));

If you wish to make two fetch API requests then you can simply use two fetch APIs:

fetch('http://example.com/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));
fetch('http://example.com/albums.json')
  .then(response => response.json())
  .then(data => console.log(data));

As they are asynchronous resource requests, the console may display the albums data before the movies data.

Is it possible to copy each of the returned data to global variables so that is visible anywhere in the code?

Yes. You need to provide code that executes when the promise is resolved. In other words you need to provide a function. This is similar to needing a function to execute when a button is clicked.

it is usual to provide an anonymous function but here I have provided an ordinary named function (with arbitary name) which I hope will make things a little clearer:

var str;  // global variable
fetch('message.txt')
  .then(response => response.text())
  .then(txtString => strUpdate(txtString) );
  
function strUpdate(txt){
	str = txt;  // update global variable
	document.getElementById("message").innerText = str;
}

You can see that code working here:
http://create.mywebcommunity.org/FetchText1.html
As that’s on free web space you may get a phishing security warning.

1 Like

But then you’d have to check if the requests have already been completed anywhere you’re using the response data; e.g. if the corresponding variables are still undefined. Just store the promises instead, to which you can then add as many then() callbacks as you want, and always get the values the promises settled (or will eventually settle) with:

const movies = fetch('movies.json').then(res => res.json())
const albums = fetch('albums.json').then(res => res.json())

// And somewhere else
movies.then(console.log)
albums.then(console.log)

// Also works with Promise.all() which is convenient
// if you need both promises to be fulfillled
Promise.all([movies, albums]).then(values => {
  console.log('Movies', values[0])
  console.log('Albums', values[1])
})
3 Likes

But in that case you do every time a fetch you ask for the data. This creates unneeded data transfer (not nice if you use it with mobile data) and reduce the performance massively.

I don’t like this idea,

If the requests are consolidatable, then i agree.

But if they’re not(m3g4’s example shows pulling data from two different files (locations)…) then you’ve no choice but to call 2 fetches.

Promise.all does not reinvoke the promises contained in its list, it merely waits for all such promises to be completed (Though arguably you may want Promise.allSettled() rather than .all, depending on your use case).

I didn‘t mean the two different fetches. That’s of course ok, but if you do not save the fetch result in a variable (where I recommend not to use a global one of course) to use it again, but only save the promise, every time you use the variable movies you will have a new fetch which might return always the same data again and again

except that what movies would be is the Promise returned by the then, which is resolved, and has a value. So it wouldnt be a new fetch?

Yes that’s what I meant with

Once settled, a promise will always resolve with the same value, or reject with the same reason. Consider:

const p = new Promise((resolve, reject) => {
  console.log('Invoking promise executor')
  setTimeout(resolve, 1000, 42)
})

p.then(console.log)
p.then(console.log)

// Logs:
// Invoking promise executor
// 42
// 42

This also applies to fetch, so there will just be a single request for each call.

This worked for me. I have another question that kind of came up as I was adjusting my code. Since I am sending multiple API requests to the same domain but with different JSON objects in the body. Is there a way to send the same API request (same URL) but with multiple JSON objects in the body? If so can you show a small piece of code that sends two JSON objects in the request?

Sorry, I should have mentioned this in my original post but I am kind of working on this a little bit at the time.

JSON is a data format that can describe multiple objects. Here by way of very simple example is the description of two telephones (based on JSON example in Wikipedia):

{
  "telephones": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    }
  ]
}

You sure can. The question is whether the server understands what you want when you do that. You’d have to check the documentation for that. Or ask someone if there is no documentation.

Further to that statement… most API’s will not. For starters, most (REST) API’s have discrete endpoints - that is to say, when you query for movies, you’ll call http://example.com/api/movies. That way the server knows what you’re requesting, and how to handle it. This is beneficial to the server in numerous ways (security because they have defined endpoints rather than trying to guess at any incoming data; tracking requests becomes simpler because data will flow from a specific api call; no ambiguity as to the incoming data for a script to try and handle, traffic monitoring and data usage from having a roughly-standard size input and output, throttling for users to make sure that one user can’t jam up the entire API, etc)

If you’re trying to query for movies and actors… the movies API doesnt know how to handle an object for the the actors API, and vice-versa. It’s a straight in-out process; request one set of data. Receive one set of data. Repeat.

2 Likes

I am passing the query as a large JSON object, Some of these properties include “from” and “to” dates. This works for me just fine when I hard-code these values such as

let startDate = "2022/07/01";
let endDate = "2022/07/31";

but since I moved JSON object to file (file#1.js) and added a jQuery date picker it doesn’t work since file#2.js which contains my fetch function doesn’t receive these dates on time. My HTML file loads these in this order…

    <script src="file#1.js"></script>
    <script src="file#2.js"></script>

What is the best way to do this short of putting all the code into one JS file?

Thanks

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.