Reputation: 2932
I'm trying to have my ajax call retry if it fails initially. It does it 3 times each time if the initial ajax call fails with a timeout of 5 seconds. The function is being imported on my vue component as a method and being called on ready()
export function getOrderStatus (order) {
let url = `/orders/status/${order.id}`
let promise = this.$http.get(url)
function retry(order, path, promise, retryAttempt) {
promise.then((response) => {
if (response.body.status === 'success') {
showOrderStatus()
}
}, (response) => {
if (retries < 2) {
retryAttempt++
setTimeout(retry(order, path, promise, retryAttempt), 5000);
} else {
handleError()
}
})
}
retry(order, path, promise, 0)
}
Component
import { getOrderStatus } from '../shared'
export default {
name: 'order-page',
props: { order },
methods: { getOrderStatus },
ready() {
this.getOrderStatus(order)
}
}
I'm not sure if this is the best way to go about retrying ajax calls so any advice would be appreciated.
Upvotes: 0
Views: 1123
Reputation: 6574
You will need to refactor this because you are caching promise
. The issue here is that Promises by nature will only complete once, resolving or rejecting. Therefore if your $http request does fail, your future calls to retry()
will all also fail without calling the endpoint.
Try something like below:
component could be refactored to a mixin if you want to share it across components (rather than import { getOrderStatus } from '../shared'
)
data () {
return {
attempt: 0,
}
}
methods: {
showOrder () { // or whatever needs this
this.getOrderStatus('order-123')
.then((reponse) => this.showOrderStatus())
.catch((reponse) => this.handleError(response))
},
getOrderStatus (order) {
this.attempt = 0
return
new Promise((resolve, reject) => this.callOrderEndpoint({
order,
resolve,
reject,
}))
},
callOrderEndpoint ({ order, resolve, reject }) {
const url = `/orders/status/${order.id}`
this.$http
.get(url)
.then((response) => {
if (response.body.status === 'success') {
resolve()
} else {
reject()
}
})
.catch(response) => {
if (this.attempt++ < 2) {
setTimeout(() =>
this.callOrderEndpoint({ order, resolve, reject }),
5000))
} else {
reject(response)
}
})
},
showOrderStatus () {
// whatever this does
},
handleError (response) {
console.error('fail')
},
},
I thought a better way to go would be to return a Promise from getOrderStatus
. This would allow you to move your success / fail methods to the then / catch methods for better structure.
Upvotes: 2