如果发生错误,如何调用 API 两次?

How to call an API twice if there is an error occurred?

我有一个内部 API 想要 post 数据。取决于某些情况,我看到错误。所以我想做的是在发生错误时再次调用它。

我所做的是创建一个计数器将其传递给函数并递归调用函数,如下所示。这给了我如下错误:

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block or by rejecting a promise which was not handled with .catch(). (rejection id: 1)

我是这样调用函数的:

....
private RETRY_API = 1;
....

 try {
    await this.callAPI(request, this.RETRY_API);
} catch (error) {
    console.log('error', error);
}

这个程序永远不会到达上面的 catch 块。

这是我调用 API:

的实际函数
private async callAPI(request, retry) {
    return new Promise((resolve, reject) => {
       someService.postApiRequest('api/url', request, async(err: any, httpCode: number, data) => {
     if (this.RETRY_API == 2) {
         return reject(err);
      } else if (err) {
          this.callAPI(request, retry);
          this.RETRY_API++;
      } else if ( httpCode !== 200 ) {
          this.RETRY_API = 2;
          // some stuff
      } else {
           this.RETRY_API = 2;
           // some stuff
           return resolve(data);
      }
   });
  })
}

不确定我错过了什么。如果有更好的方法在发生错误时调用 API 两次,请告诉我,那就太好了。

看来您需要在 callAPI 函数中的 this.callAPI(request, retry); 行的开头添加 return await

同样,有些条件块不会解决或拒绝承诺。虽然它可能工作正常,但它被认为是不好的做法。您想要解决或拒绝承诺。

当我使用 axios' interceptors functions.

收到错误时,我已经完成了第二次调用 API

这是您可以查看的代码片段:

axios.interceptors.response.use(
    // function called on a successful response 2xx
    function (response) {
        return response;
    },
    // function called on an error response ( not 2xx )
    async function (error) {
        const request = error.config as AxiosRequestConfig;
        
        // request is original API call
        
        // change something about the call and try again
        // request.headers['Authorization'] = `Bearer DIFFERENT_TOKEN`;
        // return axios(request)
        
        // or Call a different API
        // const new_data = await axios.get(...).then(...)
        // return new_data
        
        // all else fails return the original error
        return Promise.reject(error)
    }
);

尝试替换

if (this.RETRY_API == 2)

if (this.RETRY_API > 1)

让我们以不同的方式组织。首先,api...

的 promise-wrapper
private async callAPI(request) {
  return new Promise((resolve, reject) => {
    someService.postApiRequest('api/url', request,(err: any, httpCode: number, data) => {
      err ? reject(err) : resolve(data);
    });
  });
}

一个使用 setTimeout 的实用程序函数...

async function delay(t) {
  return new Promise(resolve => setTimeout(resolve, t));
}
  

现在,一个延迟调用和重试的函数...

private async callAPIWithRetry(request, retryCount=2, retryDelay=2000) {
  try {
    return await callAPI(request);
  } catch (error) {
    if (retryCount <= 0) throw err;
    await delay(retryDelay);
    return callAPIWithRetry(request, retryCount-1, retryDelay);
  }
}

如果你不能在 api 上强制失败以其他方式测试错误路径,你至少可以试试这个...

private async callAPIWithRetry(request, retryCount=2, retryDelay=2000) {
  try {
    // I hate to do this, but the only way I can test the error path is to change the code here to throw an error
    // return await callAPI(request);
    await delay(500);
    throw("mock error");
  } catch (error) {
    if (retryCount <= 0) throw err;
    await delay(retryDelay);
    return callAPIWithRetry(request, retryCount-1, retryDelay);
  }
}