如何让自定义错误代码检查axios响应拦截器?

时间:2019-09-08 05:59:46

标签: javascript 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 中的值,而不是 status

1 个答案:

答案 0 :(得分:1)

没有错误时,将调用拦截器的第一个回调。您可以根据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!