0

I trying to get a download of a json file from an API. To do that, I need to call 3 endpoints.

http://url.com/export

it returns a json: {"exportLoading":true,"file":"export-20190618-183316.json"}

After that I should call the second endpoint and check the status of this exportation:

http://url.com/export/status

it returns true or false (while server is processing, this endpoint returns true. When it returns false the file is done to make a download.)

So, if the status === false, I can call the last endpoint http://url.com/download/file_name (I make this request passing the file name - returned from the first request - to download the file.

My question is, how can I check if the second endpoint returns false to make the last request and download the file?

I just did it until the second endpoint.

app.get('/export', function (req, res, next) {

    global.fetch = fetch
    global.Headers = fetch.Headers;

    const headers = new Headers();
    const username = 'user';
    const password = 'pass';
    const URL = 'http://url.com/export'
    headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));

    fetch(URL, {
        method: 'GET',
        headers: headers,
    })
    .then(res => res.json())     
    .then(json => {            
            fetch("http://url.com/exportl/status", { 
            method: 'GET',
            headers: headers,
        }).then(result => ...) 
    })
    .catch(function (error) {
        console.log(error)
      }) 
});
mr.abdo
  • 445
  • 1
  • 5
  • 15

1 Answers1

1

You could use a while loop that will call the endpoint until the condition is met:

app.get('/export', async function(req, res, next) {

  global.fetch = fetch
  global.Headers = fetch.Headers;

  const headers = new Headers();
  const username = 'user';
  const password = 'pass';
  const URL = 'http://url.com/export'
  headers.set('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(URL, {
    method: 'GET',
    headers: headers,
  }).then(r => r.json)
  .then(data => {
    // use data here
    var status = false
    while (!status) {
      status = await checkStatus()
    }
    // third call
  })
});


function checkStatus() {
  return fetch("http://url.com/exportl/status", {
    method: 'GET',
    headers: headers,
  }).then(r => r.json)
}

Note, I do not know the response from the status, you will have to change the code to accommodate the response.

Kobe
  • 6,226
  • 1
  • 14
  • 35
  • 1
    This didn't convince me, it could have performance issues since the optimizer won't be able to clean the stack. So you're polluting the stack with an infinite amount of function calls. Maybe it's better avoiding returning `checkStatus()` – Christian Vincenzo Traina Jun 19 '19 at 10:46
  • 1
    That's the point of a recursive function. You could add a delay depending on how intensive the request is, and you could return and call `checkstatus()` again outside of itself. – Kobe Jun 19 '19 at 10:50
  • 1
    @CristianTraìna what do you think to the edit instead? – Kobe Jun 19 '19 at 10:59
  • 1
    I'd avoid returning both `fetch` and `checkStatus` and keep the recursion. In this way, the optimiser will notice that the result of `checkStatus` is not used and it will clear the stack. How do we send the result? Well, maybe it's the case to use the old-styled callbacks – Christian Vincenzo Traina Jun 19 '19 at 12:03
  • 1
    These are the stack limits in different browsers: https://stackoverflow.com/questions/7826992/browser-javascript-stack-size-limit . Those numbers are also the limit of attempts in your solution – Christian Vincenzo Traina Jun 19 '19 at 12:04
  • It helps me a lot. I'm gonna take a look at what you guys are talking about. My question now is, how can I get the json response of the first request? I need it to get the file name and then call the last request `http://url.com/download/file_name` – mr.abdo Jun 19 '19 at 12:08
  • @mr.abdo You would just pass the value in from the first `.then()` – Kobe Jun 19 '19 at 12:15
  • @CristianTraìna My bad, i forgot to remove that when i asked you to look at my edit, i moved it to a while loop so there is no stack – Kobe Jun 19 '19 at 12:21
  • @Kobe could send me a example of how to passa the value? I'm trying but I'm getting `undefined` – mr.abdo Jun 19 '19 at 12:30
  • 1
    @mr.abdo check my edit. Again, im not sure what data you get back, so you might not need the `.then(r => r.json())`. – Kobe Jun 19 '19 at 12:33