How to optimize the request structure of api in code

Posted by the182guy on Sun, 07 Nov 2021 21:07:35 +0100

(Note: vue project is taken as an example below)

1, Call mode of api in general project

1. Directory structure

|── src
|-- utils (tools and methods folder)
|-- http.js (encapsulated request method)
|- | - | - views (page folder)
|- | - | - | - device (can be understood as a level-1 menu)
|- | - | - | - | - board (can be understood as secondary menu page)
|── |── |── |── |── |── index.vue

2. Common api call forms

Step 1: generally, axios get,post and other methods are encapsulated in http.js, and interceptors are used to uniformly process the logic before the request and after the response.
Bind HTTP to vue instance, Vue.prototype.$http = http
The second step: call in the above index.vue.

<script>
export default {
  data () {
    return {
      data: ""
    }
  },
  methods: {
    async getData () {
    const { data } = await this.$https.get("/url/test")
    this.data = data
  }
 }
</script>

3. Problems

(1) The back-end address we passed in is "/ url/test". If we want to continue to use it, we still need to write this.$https.get("/url/test");
(2) When there are a large number of interface calls in the page, the interface address will be difficult to manage. Can you create a new file for unified management?

2, api organization structure in ideal project (optimization 1)

1. Directory structure

We should have an api folder to store the interface of the current corresponding module
This is defined in board.js

import { http } form '@/utils/http.js'
export default {
  getBoardData () {
    return http.get("/url/test")
  }
}

|── src
|── |── utils
|── |── |── http.js
|── |── |── views
|- | - | - | - device (can be understood as a level-1 menu)
|- | - | - | - | - board (can be understood as secondary menu page)
|── |── |── |── |── |── index.vue
|── |── api
|- | - | - common
|── |── |── |── index.js
|- | - | - device (first level menu name)
|- | - | - | - board.js (secondary menu page name)
|── |── |── index.js

2. Call

It is used in index.vue under the board module

<script>
import boardApi from "@/api/device/board.js"
export default {
  data () {
    return {
      data: ""
    }
  },
  methods: {
    async getData () {
    const { data } = await boardApi.getBoardData()
    this.data = datad
  }
 }
<script>

3. Problems

(1) import every time. Can you use a global variable to load these interface files in the form of $service.getData()

3, api organization structure in ideal project (optimization 2)

1. require.context of webpack

Create your own context through the require.context() function.
You can pass three parameters to this function: a directory to search, a flag indicating whether to search its subdirectories, and a regular expression matching files.

// Find all files ending in. js in the current directory, including subdirectories
const files = require.context("./",true, "\.js$") 

So we can use the webpack's require.context to get our file structure

2. index.js in api folder

|── src
|── |── utils
|── |── |── http.js
|── |── |── views
|- | - | - | - device (can be understood as a level-1 menu)
|- | - | - | - | - board (can be understood as secondary menu page)
|── |── |── |── |── |── index.vue
|── |── api
|- | - | - common
|── |── |── |── index.js
|- | - | - device (first level menu name)
|- | - | - | - board.js (secondary menu page name)
|── |── |── index.js

// index.js of api file
const files = require.context('./', true, /\.js$/)

const commonApis = {}

files.keys().forEach(key => { //The keys() of require.context returns a file path matching array
 
  if (key === './index.js') {
    return false
  }
  const arr = key.match(/\.\/(.*)\/(.*).js)
  /**
  * commonApis Structure of
  * {
  *   device: {
  *     getBoardData () {}
  *   }
  *
  * }
  */
  commonApis[arr[1]] = { ...commonApis[arr[1]], ...files(key).default }
})
export default commonApis

3. Call

  //Structure of commonApis
  {
   device: { // First level menu name
      getBoardData () {}
    }
  }

Above, we get a commonApis object. We have to bind it to a variable, such as $service
Therefore, it needs to be defined in vue.config.js

const webpack = require('webpack')
const path = require('path')
function resolve (dir) {
  return path.join(__dirname, dir)
}

module.exports = {
  // Adjust the webpack configuration (place plugins, etc.)
  configureWebpack: {
    resolve: {
      alias: { // Alias path
        service: resolve('src/api/index.js')
      }
    },
    plugins: [
      new webpack.ProvidePlugin({ // Plug in for automatic loading module
        $service: ['service', 'default'],
      })
    ]
  }
}

In this way, you can call index.vue in board

<script>
export default {
  data () {
    return {
      data: ""
    }
  },
  methods: {
    async getData () {
    const { data } = await $service.device.getBoardData()
    this.data = data
  }
 }
</script>

Topics: Vue