Magren

Magren

Idealist & Garbage maker 🛸
twitter
jike

Encapsulation and usage of axios in Vue Typescript

August has arrived, and a strange opportunity has also hit me in the face. I packed my luggage and ran to Guangzhou alone to join a project started by a senior brother who had graduated. With a little uneasiness and excitement, I took the first step away from school.

Since I lived in a room in the office, I started a work-life of working from five in the morning until nine at night. At night, I worked on my own project, feeling a bit like the summer training camp under the starry sky. It was tiring but fulfilling. Every day, I also worried about losing hair and what to eat.

I sent a copy of the map of Huaguang that I wrote to my EO, but it was confiscated. It went online as a product of Starry Sky and required further improvement 😟
I thought about adding a click event to each marker of each location, so that when clicked, the detailed introduction of that location can be seen. However, each place needs a picture, and storing them locally would take up too much space and possibly cause lagging. So, I decided to store them on the server. I re-read axios and learned from some online tutorials to create a wrapper and solve the cross-origin issue.

Wrapper for axios#

import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'

const showStatus = (status: number) => {
  let message = ''
  switch (status) {
    case 400:
      message = 'Request Error (400)'
      break
    case 401:
      message = 'Unauthorized, please log in again (401)'
      break
    case 403:
      message = 'Access Denied (403)'
      break
    case 404:
      message = 'Request Error (404)'
      break
    case 408:
      message = 'Request Timeout (408)'
      break
    case 500:
      message = 'Server Error (500)'
      break
    case 501:
      message = 'Service Not Implemented (501)'
      break
    case 502:
      message = 'Network Error (502)'
      break
    case 503:
      message = 'Service Unavailable (503)'
      break
    case 504:
      message = 'Network Timeout (504)'
      break
    case 505:
      message = 'HTTP Version Not Supported (505)'
      break
    default:
      message = `Connection Error (${status})!`
  }
  return `${message}`
}

const service = axios.create({
  // Joint debugging
  baseURL: 'https://www.wanandroid.com',
  headers: {
    get: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'
    },
    post: {
      'Content-Type': 'application/json;charset=utf-8'
    }
  },
  // Whether to allow cross-site access control requests
  withCredentials: true,
  timeout: 30000, // Timeout time
  transformRequest: [(data) => {
    data = JSON.stringify(data)
    return data
  }],
  validateStatus () {
    // Using async-await, handling reject cases is cumbersome, so all are returned as resolve, and exceptions are handled in the business code
    return true
  },
  transformResponse: [(data) => {
    if (typeof data === 'string' && data.startsWith('{')) {
      data = JSON.parse(data)
    }
    return data
  }]
})

// Request interceptor
service.interceptors.request.use((config: AxiosRequestConfig) => {
    return config
}, (error) => {
    // Error thrown to the business code
    error.data = {}
    error.data.msg = 'Server Exception'
    return Promise.resolve(error)
})

// Response interceptor
service.interceptors.response.use((response: AxiosResponse) => {
    const status = response.status
    let msg = ''
    if (status < 200 || status >= 300) {
        // Handling http errors, thrown to the business code
        msg = showStatus(status)
        if (typeof response.data === 'string') {
            response.data = {msg}
        } else {
            response.data.msg = msg
        }
    }
    return response
}, (error) => {
    // Error thrown to the business code
    error.data = {}
    error.data.msg = 'Request Timeout or Server Exception'
    return Promise.resolve(error)
})

export default service

Usage#

@Component
export default class Home extends Vue{
  a = []
  getSomeThings(){
    return request({
        url: "/wxarticle/list/408/1/json",
        method:'get'
    }).then((response)=>{
      this.a = response.data.data.datas
      console.log(this.a)
    }).catch((error)=>{
      console.log(error)
    })
  }

 mounted(){
   this.getSomeThings()
 }

Solving the Cross-Origin Issue#

Regarding what cross-origin is, we have already learned about it in AJAX. It is caused by the same-origin policy of the browser, which is a security measure imposed by the browser on JavaScript.

Approach to solving the cross-origin issue with axios#

We can configure a proxy server to request data from another server, then return the requested data to our proxy server, and finally return the data to our client. This way, we can achieve cross-origin access to data.

Configuring the proxy

Configure the following content in our vue.config.js file:

module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'https://www.wanandroid.com',// The IP+port of the backend interface you want to request
                changeOrigin: true,// Allowing cross-origin, a virtual server will be created locally to send and receive data, so there will be no cross-origin issues in the interaction between the server and the client
                ws: true,// Enable webSocket
                pathRewrite: {
                    '^/api': '',// Replace with the content in the target
                }
            }
        }
    }
}
Configuring baseURL

In our axios wrapper file, change the baseURL to '/api':

const service = axios.create({
  baseURL: '/api',

  …………

})

So, what do the above two steps mean? Actually:

When we request '/wxarticle/list/408/1/json', it is equivalent to requesting: localhost:8080/api/wxarticle/list/408/1/json,
Then, the configured proxy intercepts '/api' and replaces it with the content in the target,
Therefore, the actual requested URL is https://www.wanandroid.com/wxarticle/list/408/1/json,
Thus, we have successfully requested the interface we need.

Finally#

Now that we have understood it, let's get started,

What about the pictures from the school?

Ah? There are none.

What about the photography part? 😧

They... only have a part... 😧

Ah... this... 😩

In summary, the project is currently on hold 💢

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.