2

I have the following chain.

  return axios
        .get(actionUrl, {
            params: {
                action: 'action3'
            },
        })
        .finally(() => axios.get(actionUrl, {
            params: {
                action: 'action3'
            },
        }))
        .finally(() => axios.get(actionUrl, {
            params: {
                action: 'action6'
            },
        }))
        .finally(() => axios.get(actionUrl, {
            params: {
                action: 'action1'
            },
        }))

I have to sequentially call different endpoints in order even if the previous one fails. However in case an endpoint timeouts I want to break the chain. Is it achievable without using .then and .catch and repeating the same code in them?

Thanks.

scarably
  • 333
  • 1
  • 4
  • 11
  • 1
    No. This is precisely what you should use `then` and `catch` for. Why would you want to use `finally`? – Bergi May 06 '20 at 08:46
  • Btw, you already *are* repeating the same code in all lines. Can you post your real code so that we can advise on how to restructure it? – Bergi May 06 '20 at 08:48
  • They are the same calls with different query param which have to be made in order. – scarably May 06 '20 at 11:33
  • [This might be useful](https://stackoverflow.com/a/32049994/3478010) – Roamer-1888 May 06 '20 at 21:49

3 Answers3

1

The finally function is there precisely to make sure that the function inside runs even if there is an exception. You can get the behaviour you want by using just one finally like this:

axios.get()
  .then(() => doStuffOnSuccess())
  .finally(() => {
    axios.get().then(() => doFinallyStuff1())
       .then(() => doFinallyStuff2())
       .then(() => doFinallyStuff3())
       .catch(e => console.error("Finally had trouble",e));
  });

This way if anything within the finally function times out or fails it will break the chain. By having the final catch you will avoid it throwing back further up the chain.

This assumes that you are using finally correctly and everything in that should always get executed after the previous calls finish even if there are errors.

Always Learning
  • 5,510
  • 2
  • 17
  • 34
0

Are you familiar with async/await? Generally you shouldn't chain finally like this, it's always better to create recurent function for example:

const fetchSomething = async () => {
   try { 
     const result = await axios.get();

     if (...when fetching should stop...) {
       return result;
     }

     return fetchSomething();
   } catch(error) {
     return fetchSomething();
   }
}

But with reccurent function is extremely important to create some kill switch to prevent executing it forever - for example set some kind of timeout, 1 minute or so and if this limit is exceeded then stop executing. It will be probably even more easier with generators and yield but I never used this solution

Darek Gala
  • 157
  • 1
  • 2
  • 7
0

This is achievable with then and catch. You should not use finally if you don't want the callback to run in case of an error.

I have to sequentially call different endpoints in order even if the previous one fails. However in case an endpoint timeouts I want to break the chain

So you want to not call them when the previous one fails (with a timeout), all you want to do is to ignore non-timeout errors. That's what catch should be used for:

function callEndpoint(action) {
  return axios.get(actionUrl, { params: { action } }).catch(err => {
    if (isTimeout(err))
      throw err
    else
      ; // ignore the error, return undefined
  })
}

Then just chain them:

callEndpoint('action3').then(() => callEndpoint('action6')).then(() => callEndpoint('action3'))
Bergi
  • 630,263
  • 148
  • 957
  • 1,375