scarably
scarably

Reputation: 333

Break a .finally() chain

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.

Upvotes: 2

Views: 721

Answers (3)

Bergi
Bergi

Reputation: 664346

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'))

Upvotes: 0

Always Learning
Always Learning

Reputation: 5581

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.

Upvotes: 1

Darek Gala
Darek Gala

Reputation: 177

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

Upvotes: 0

Related Questions