首页 > 解决方案 > 如何对 axios 响应拦截器进行自定义错误代码检查?

问题描述

我在我的应用程序中使用了 graphql,它错误地发送了以下响应。

您可能已经注意到,graphql 将所有错误作为状态码 200 发送。我从 API 返回的错误在data.errors.

{
  "data": {
    "errors": [
      {
        "message": "Error: Token has expired",
        "locations": [
          {
            "line": 3,
            "column": 7
          }
        ],
        "path": [
          "createGame"
        ],
        "extensions": {
          "code": "403",
          "exception": {
            "stacktrace": [
              "Error: Error: Token has expired"
            ]
          }
        }
      }
    ],
    "data": {
      "createGame": null
    }
  },
  "status": 200,
  "statusText": "OK",
  "headers": {
    "content-type": "application/json; charset=utf-8"
  },
  "config": {
    "url": "http://localhost:4200/graphql",
    "method": "post",
    "data": "{\"query\":\"\\n    mutation {\\n      createGame (name: \\\"SA\\\", shortName: \\\"s\\\") {\\n        id,\\n        name,\\n        shortName\\n      }\\n    }\\n  \"}",
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "Content-Type": "application/json",
      "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJlbXBsb3llZUlkIjowLCJ1c2VyUm9sZUlkIjozLCJwYXNzd29yZCI6IiQyYiQxMCRwNTE2V1hnSGZXdWx6czVmY2o2ZGp1Q09lUzF0UUw3U2MySEIuMDRPUmpWekh6VnduSTNwNiIsImlzQWN0aXZlIjp0cnVlLCJjcmVhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjAzOVoiLCJ1cGRhdGVkQXQiOiIyMDE5LTA4LTE5VDA5OjMxOjA5LjA0MVoifSwiaWF0IjoxNTY3ODcyNTk2LCJleHAiOjE1Njc4NzI2MDZ9.HpNE9m5YEUv0qgBHxsEoQMd1p29TkOqvQzYF7ptljJ0"
    },
    "baseURL": "http://localhost:4200/graphql",
    "transformRequest": [
      null
    ],
    "transformResponse": [
      null
    ],
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1
  },
  "request": {}
}

我遇到的问题是我在前端集成了 axios 响应拦截器

http.interceptors.response.use(
    /**
     * Leave response as it is.
     */
    (response: any) =>  response,
    /**
     * This interceptor checks if the response had a 401 status code, which means
     * that the access token used for the request has expired. It then refreshes
     * the access token and resends the original request.
     */
    unauthorizedResponseHandlerInterceptor
  );

并且该unauthorizedResponseHandlerInterceptor函数仅在出现错误时由 Axios 调用,但我的 graphql 服务器将状态返回为 200,因此不会调用该函数。

我有什么办法可以修改 axios 响应拦截器,以便它检查data.errors中的值而不是状态

标签: javascriptaxios

解决方案


没有错误时调用拦截器的第一个回调。您可以根据 API 发送错误的方式进行一些自定义检查:

http.interceptors.response.use(
    /**
     * Leave response as it is.
     */
    (response: any) => {
      if (response.data.errors) {
          let customError = new Error(response.data.errors[0].message);
          response.original_status = response.status
          response.status = response.data.errors[0].extensions.code
          customError.response = response;
          return Promise.reject(customError);
      }
      return response;
    },
    /**
     * This interceptor checks if the response had a 401 status code, which means
     * that the access token used for the request has expired. It then refreshes
     * the access token and resends the original request.
     */
    unauthorizedResponseHandlerInterceptor
  );

它非常灵活。如上所示,您甚至可以通过Promise.reject()在拦截器中返回来将成功的调用变成错误。

这是一个可以玩的小提琴:https ://jsfiddle.net/acdcjunior/pvb1kj87/

axios.interceptors.response.use((response) => {
  if (response.data.errors) {
    let customError = new Error(response.data.errors[0].message);
    response.original_status = response.status
    response.status = response.data.errors[0].extensions.code
    // add some properties to make it look like a regular axios error
    customError.response = response;
    customError.request = response.request;
    customError.config = response.config;
    customError.isAxiosError = true; // or not

    return Promise.reject(customError);
  }
  return response;
}, (error) => {
  // Do something with response error
  return Promise.reject(error);
});

(async () => {

  console.log('*** regular axios error:')

  await axios.get(`https://example.com/DOESNOTEXIST`)
    .then((data) => {
      console.log('success -->', data)
    })
    .catch((e) => {
      console.log('error -->', e)
    })

  console.log('*\n*\n*')
  console.log('*** simulating error:')

  axios.get(`https://api.myjson.com/bins/d7hbp`)
    .then((data) => {
      console.log('success -->', data)
    })
    .catch((e) => {
      console.log('error -->', e)
    })

})();
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
Open dev tools and check the console!


推荐阅读