“This is the 20th day of my participation in the August Gwen Challenge.

This article mainly introduces the interface request encapsulation based on TS and AXIOS

Train of thought

  • Request to intercept

    • Add some parameters to the request header, such as token, UID, etc
    • Check the login status of the user. If the user does not log in, directly log in
    • Data format for sending requests, JSON → Urlencoded (optional)
  • The response to intercept

    • Determine the service status code of the back-end response and perform different processing

      • For example, if the login status of a user has expired, the user can log in directly
      • Unified error notification

Write the code for the routine first:

import axios, {
    AxiosInstance,
    AxiosResponse,
    AxiosRequestConfig,
    AxiosError
} from 'axios'
export default abstract class HttpClient {
    protected readonly instance: AxiosInstance

    public constructor(baseURL = '/api', timeout = 1000 * 120) {
        this.instance = axios.create({
            baseURL,
            timeout
        })
        // 1. Request interceptor
        this._initializeRequestInterceptor()
        // 2. Response interceptor
        this._initializeResponseInterceptor()
    }
    private _initializeRequestInterceptor = () = > {
        this.instance.interceptors.request.use(
            this._handleRequest,
            this._handleError
        )
    }
    private _handleRequest = (config: AxiosRequestConfig) = > {}
   
    private _initializeResponseInterceptor = () = > {
        this.instance.interceptors.response.use(
            this._handleResponse,
            this._handleError
        )
    }
    private _handleResponse = (response: AxiosResponse) = > {}
    protected _handleError = (error: AxiosError) = > Promise.reject(error)
}

Copy the code

To recap the above code, we create an HttpClient class for the request interface. Constructor defines baseURL and timeout, as well as request and response interception methods.

At this point, the process for initiating an interface is as follows:

  1. Call request interception before sending the request
  2. Sending interface, network has a request
  3. Interface response, invoke response interception
  4. The response is given to the front-end program to execute the corresponding logic

Request to intercept

Starting with the detailed logic, when requesting interception, you can do the following:

  • Add some parameters to the request header, such as token, UID, etc
  • Check the login status of the user. If the user does not log in, directly log in
  • Data format for sending requests, JSON → Urlencoded (optional)
     private _handleRequest = (config: AxiosRequestConfig) = > {
        //1. Add a custom request header
        config.headers['Authorization'] = 'my token'
        config.headers['mobile'] = 'my mobile'
        //2. Check whether toke exists.
        
        //3. Convert the data format
        config.data = qs.stringify(config.data)
        return config
    }
Copy the code

The response to intercept

Once the response is received, the processing is as follows:

  1. Determine the service status code of the back-end response and perform different processing
    • If the login status of the user expires, the user can directly log in
    • Unified error notification
  2. Save the token
 // Response interceptor
    private _handleResponse = (response: AxiosResponse) = > {
        const { data, headers } = response

        //1.-- Process the token of the response, save the token
        const token = headers['authorization']
        if (token) {
            this._saveToken(token)
        }
       
        //2. -- Handle the response code by try-catch, if the interface does not return code, return it directly
        try {
            const code = data.code,
            message = data.desc || data.msg
            const isSucceed = this._handleResCode(code, message, url)
            if (isSucceed) {
                return Promise.resolve(data)
            } else {
                return Promise.reject(message)
            }
        } catch (error) {
            return Promise.resolve(data)
        }
       
    }
    / / save the token
    private _saveToken(token: string) {
        const USER = getModule(UserModule)
        USER.setToken(token)
    }
    private _handleResCode(code: number, message: string, url: string) {
        if (code === 0) {
            // The request succeeded
            return true
        } else if (code===4000) {
            // The token is invalid and the login page is jumped back
            Vue.prototype.$message.error('Id expired, please log in again')
            router.push({ name: 'login' })
            return false
        } else {
            // In other cases, message is displayed
            Vue.prototype.$message.error(message)
            return false}}Copy the code

Use httpClient.ts to define the request

The proposed request-related files are defined under the @/ API directory as follows

httpClient.ts
user.ts
uti.ts
Copy the code

Define the request in the corresponding file, precautions

  1. All request classes need inheritanceHttpClientClass,HttpClient does some unified interception and unified handling of requests and responses
  2. The request response data needs to provide a type, which is defined in@/types/xxxFile, a module for a file. Only when the type is provided will there be a code prompt
import HttpClient from './HttpClient'
import { AlarmItemType } from '.. /types/test'
import { BaseResType } from '.. /types/index'

class UtilApi extends HttpClient {
   / / such as the background the response returned res = {code: XXX, data: XXX, token: XXX, desc: XXX}
    // We need to define the type of res.data which is the first parameter of get, AlarmItemType
    BaseResType
      
        = BaseResType
       
      
    public getAlarmById = (id: string) = >
        this.instance.get<AlarmItemType, BaseResType<AlarmItemType>>(
            `/realtime/alarms/queryByAlarmId/${id}`)}export const UTIL_API = new UtilApi()
Copy the code

Request the interface in the component

Type the key word of the request module in the component that needs to send the request, such as USER_API. If the plug-in TypeScript Importer is installed, the corresponding module import prompt will be displayed. At this time, enter Enter to import the corresponding module.

<template>
    <section>Request data :{{alarmData}}</section>
</template>

<script lang="ts">
import { UTIL_API } from '@/api/utilApi'
import { Vue, Component } from 'vue-property-decorator'
@Component({
    components: {}})export default class TestRequest extends Vue {
    alarmData = {}
    async getAlarmData() {
        const res = await UTIL_API.getAlarmById('alarmIdc7e9bd47')
        if (res.code == 0) {
            this.$message.success('Request successful')
            this.alarmData = res.data
        }
    }
    mounted() {
        this.getAlarmData()
    }
}
</script>
<style lang="scss" scoped></style>
Copy the code