使用递归重试vue资源ajax调用

时间:2016-11-30 22:11:23

标签: javascript ajax vue.js vue-resource

如果最初失败,我试图让我的ajax调用重试。如果初始ajax调用失败且超时为5秒,则每次执行3次。该函数作为方法导入我的vue组件,并在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)
}

组件

  import { getOrderStatus } from '../shared'

  export default {
   name: 'order-page',
   props: { order },
   methods: { getOrderStatus },
   ready() {
     this.getOrderStatus(order)
   }
 }

我不确定这是否是重试ajax呼叫的最佳方式,因此任何建议都会受到赞赏。

1 个答案:

答案 0 :(得分:2)

您需要重构此内容,因为您正在缓存promise。这里的问题是承诺本质上只会完成一次,解决或拒绝。因此,如果您的$ http请求失败,您未来对retry()的调用也将在不调用端点的情况下全部失败。

尝试以下内容:

组件可以重构为mixin,如果您想跨组件共享它(而不是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')

    },

},

我认为更好的方法是从getOrderStatus返回一个承诺。这将允许您将成功/失败方法移动到then / catch方法以获得更好的结构。