如果前一个 API 调用(同一个)返回错误,如何让 API 每 2 秒调用一次?

How to make API call every 2 seconds if previous API call (the same one) returned an error?

这是一个 Vue.js 应用程序。

一切都是通过单击“保存”按钮开始的,在保存过程中,如果之前的 API 调用(同一个)返回错误 402,我需要每 2 秒调用一次 API。

代码的关键部分如下所示:

methods: {
  save() {
    ...
    Promise.all([updateOrder])
      .then(async values => {
        for (let payment of values[0].payments) {
          if ((payment.payment_type === 10 || payment.payment_type === 11) && payment.status === 0) {
            this.$axios.get(
              `${this.$config.server}/api/crm/payments/qr/${payment.id}/url`
              )
              .then(response => {
                //
              })
              .catch(error => {
                const response = error.response ?? error
                const errorCode = response?.data?.code // It returned error 402
              })
          }
        }
      })
      .catch(
        //
      )
      ...
  }
}

我想我应该使用:

setInterval(apiCall(payment), 2000)

但是,我不确定如何。

这可以通过多种方式解决,具体取决于您的代码逻辑。最简单的方法是使用 setTimeout,但您需要将该调用放在单独的函数中。

以下是模拟一个 API 呼叫将被连续拒绝 3 次,以及如何处理 setTimeout 被拒绝的情况。

let counter = 0

const apiCall = () => counter > 3 ? Promise.resolve() : Promise.reject()

const apiHandler = () => {
  console.log('Call num:', ++counter)
  apiCall()
    .then(() => console.log('Approved'))
    .catch(() => {
      console.log('Rejected')
      setTimeout(apiHandler, 2000)
    })
}

apiHandler()

另一个高级解决方案是 axios-retry 因为您使用 axios 进行 API 调用。以下是您的代码的示例:

methods: {
  save() {
    ...
    // Better to move this line to main.js file or 
    // to use custom axios instance (axios.create()) 
    // in case you want to apply axios-retry to this API call only 
    axiosRetry(this.$axios, { retries: 0 });

    const retryOptions = {
      retries: 10,
      retryDelay: () => 2000,
      retryCondition: (error) => {
        return error.response.status === 402
      },
    }

    Promise.all([updateOrder])
      .then(async values => {
        for (let payment of values[0].payments) {
          if ((payment.payment_type === 10 || payment.payment_type === 11) && payment.status === 0) {
            this.$axios.get(
              `${this.$config.server}/api/crm/payments/qr/${payment.id}/url`,
      {'axios-retry': retryOptions}
              )
              .then(response => {
                //
              })
              .catch(error => {
                const response = error.response ?? error
                const errorCode = response?.data?.code // It returned error 402
              })
          }
        }
      })
      .catch(
        //
      )
      ...
  }
}