RESTful API Integration
Table of Contents
- Introduction
- Project Structure Overview
- Core Request Encapsulation Module
- API Interface Organization Architecture
- Authentication and Security Mechanism
- Environment Configuration and Proxy
- Error Handling and Unified Response
- Caching Strategy and Performance Optimization
- Pagination and Parameter Processing
- Mock Data and Development Debugging
- Practical Usage Examples
- Best Practices and Extension Guide
Introduction
The lmes-web-base project adopts a RESTful API integration scheme based on axios, providing a complete frontend and backend communication solution. Through a well-designed request encapsulation layer, unified error handling mechanism, intelligent caching strategy, and flexible environment configuration, the system provides stable and reliable API communication capabilities for frontend applications.
Project Structure Overview
Diagram sources
Core Request Encapsulation Module
request.ts Module Architecture
request.ts is the core module of the entire API integration, deeply encapsulated based on axios, providing complete request lifecycle management.
Diagram sources
Request Interceptor Functions
The request interceptor is responsible for preprocessing before the request is sent:
- Auth Token Injection: Automatically get Token from Session storage and add to Authorization header
- Default Header Setting: Merge default Content-Type and other business-related headers
- XML String Processing: Identify and correctly handle XML formatted string data
- Silent Mode Support: Decide whether to display loading animation based on configuration
Response Interceptor Functions
The response interceptor processes data returned by the server:
- Data Extraction: Automatically extract response.data part
- Error Proxy Detection: Identify and handle interfaces not found by proxy
- Blob Type Processing: Special handling for file download scenarios
- Status Code Mapping: Map HTTP status codes to user-friendly error messages
Section sources
API Interface Organization Architecture
Project-level API Organization
The project adopts a modular API organization method, with independent API files for each business domain:
Diagram sources
API Method Type Support
The system supports complete RESTful methods:
- GET: Used for data query and resource retrieval
- POST: Used for data creation and complex query
- PUT: Used for resource update
- DELETE: Used for resource deletion
Section sources
Authentication and Security Mechanism
Token Injection Mechanism
The system implements an automated Token management mechanism:
// Automatically get Token from Session storage
const token = Session.get('Token')
// Dynamically calculate Authorization header
get Authorization() {
return token ? `Bearer ${token}` : undefined
}
Header Security Policy
- Content-Type Enforcement: Ensure all requests use application/json format
- Project Identifier: Automatically inject X-Project header to identify current project
- Client Identifier: Add X-Client-Id to support multi-client identification
- Language Environment: Dynamically set Accept-Language header
Re-login Mechanism
When encountering 401 or 403 status codes, the system will trigger a re-login popup:
Diagram sources
Section sources
Environment Configuration and Proxy
Environment Variable Driven baseURL Switching
The system supports configuring baseURL in multiple ways:
// Prioritize getting from URL parameters
let baseURL = params.get('baseURL') || ''
// Support overriding via baseURL parameter
console.info('[baseURL]', baseURL)
Development Environment Proxy Configuration
The development environment configures a complete proxy system via Vite:
Diagram sources
Path Alias Configuration
The system configures multiple path aliases to simplify imports:
@→./srccomponents→./src/componentssdk→./src/cms/sdk.es.js
Section sources
Error Handling and Unified Response
Unified Error Handling Mechanism
The system implements multi-level error handling:
Diagram sources
Error Message Processing
The system supports multiple error message sources:
- Response Body Error: Prioritize getting from
data.msg,data.message, etc. - Status Text: Use statusText as backup
- Default Message: Use "Request Error" as final backup
Loading Animation Management
The system implements intelligent loading animation management:
// Request counter
let reqNum: number = 0
// Show loading animation
const setLoading = (silent: boolean) => {
if (silent) return
reqNum++
if (reqNum === 1) {
loadingInstance = ElLoading.service(loadingOptions)
}
}
// Close loading animation
const closeLoading = (silent: boolean) => {
if (silent) return
reqNum--
if (reqNum <= 0) {
reqNum = 0
loadingInstance && loadingInstance.close()
}
}
Section sources
Caching Strategy and Performance Optimization
Memory Caching Mechanism
The system implements a memory-based caching strategy:
Diagram sources
Variable Query Caching
The system implements a 5-minute caching mechanism for variable queries:
private async queryVariable(next: () => void) {
const size = this.getState(Base.MAP_KEY)?.size
const t = this.getState(Base.CACHE_KEY) || Date.now()
// Return directly if within cache validity period
if (size > 0 && Date.now() - t < Base.CACHE_TIME) {
return next && next()
}
// Cache expired, initiate new request
try {
const vars = await request.get('/api/v1/variable/query')
const varMap = this.transformArrayToMap(vars.result)
this.setState(Base.CACHE_KEY, Date.now())
this.setState(Base.MAP_KEY, varMap)
next && next()
} catch (error) {
console.error(error, 'Variable query interface error, pause request')
}
}
Throttling and Debouncing Mechanism
The system provides high-performance throttling and debouncing tools:
export const genSetInterval = (fn: () => void, time: number = 33): Timer => {
let timerId: number | null = null
let lastTime = performance.now()
const loop = (currentTime: number) => {
const deltaTime = currentTime - lastTime
if (deltaTime >= time) {
fn()
lastTime = currentTime - (deltaTime % time) // Keep remaining time, reduce drift
}
timerId = requestAnimationFrame(loop)
}
return {
start() {
if (timerId === null) {
lastTime = performance.now()
timerId = requestAnimationFrame(loop)
}
},
clear() {
if (timerId !== null) {
cancelAnimationFrame(timerId)
timerId = null
}
},
}
}
Section sources
Pagination and Parameter Processing
Pagination Parameter Standardization
The system implements a unified pagination parameter processing mechanism:
Diagram sources
Pagination Component Implementation
The system provides two pagination components:
- BaseTable Pagination: Integrated in the table component
- MyPages Component: Independent pagination control
// Get pagination parameters
const getPaginationParams = () => {
return {
pageNum: pageNum.value,
pageSize: params.value.MaxResultCount,
totalCount: totalCount.value,
}
}
// Table scroll to specified row
const scrollToRow = async ({ row, skip }: any) => {
if (skip) {
if (totalCount.value > dataSource.value.length) {
// Jump to last page
pageNum.value = Math.ceil(totalCount.value / params.value.MaxResultCount)
params.value.SkipCount = (pageNum.value - 1) * params.value.MaxResultCount
}
await getTableList()
skipRow(dataSource.value[dataSource.value.length - 1])
} else {
skipRow(row)
}
}
Parameter Serialization Processing
The system automatically handles parameter serialization for various types:
// Automatic JSON serialization
if (
typeof config.data !== 'object' &&
!isXMLString &&
config.headers['Content-Type'].match(/application\/json/i)
) {
config.data = JSON.stringify(config.data)
}
Section sources
Mock Data and Development Debugging
Mock System Architecture
The system provides complete Mock data support:
Diagram sources
Development Environment Debugging Support
The system supports multiple development debugging modes:
- Static File Mock: Provide static data via mock.json
- Dynamic Mock: Provide dynamic behavior via index.js
- Multi-language Mock: Support localization testing
- Component Mock: Support component-level simulation
Interface Integration Mechanism
The development environment provides complete interface integration support:
// API route switching between development and production environments
return import.meta.env.PROD
? sdk.request({ url, method, params: { ...provider } })
: request({ url, method, params: { ...provider } })
Section sources
Actual Usage Examples
Basic API Call
// Get project configuration
export const getProjectConfig = (name: string) => {
return request.get(`/projectApi/env?name=${name}`)
}
// Create component
export const createWidget = (data) => {
return request.post(`/projectApi/create`, data)
}
Advanced API Call
// Product list query (with condition filtering)
function getproductList(data: any, hasFormula: boolean = true) {
const url = `api/v1/messuite/query/product?filter=${data.filter}&hasFormula=${hasFormula}`
const method = 'get'
return request({ url, method })
}
// Work section list query (with capability type filtering)
function getWorksectionList(data: any) {
const url = `api/v1/messuite/query/worksection?filter=${data.filter}&abilityType=${data.abilityType}&includeDetails=${data.includeDetails}`
const method = 'get'
return request({ url, method })
}
Error Handling Example
// Request with silent mode
try {
const result = await request.get('/api/v1/data', {
silent: true, // Do not display loading animation
unLogError: true, // Do not display error prompt
})
} catch (error) {
console.error('API call failed:', error)
}
File Upload Example
// File upload (supports FormData)
export const postImport = (file: FormData) => {
return request({
url: `/api/v1/zc/productsop/uploadsop`,
method: 'post',
contentType: 'multipart/form-data',
headers: { accept: '*/*' },
data: file,
})
}
Section sources
Best Practices and Extension Guide
Extending Custom Headers
// Add custom headers in request config
const customRequest = async (url: string, data?: any) => {
return request({
url,
method: 'post',
headers: {
'X-Custom-Header': 'custom-value',
'X-Additional-Info': 'additional-info',
},
data,
})
}
Adapting Pagination Parameter Format
// Unified pagination parameter processing
const getPagedParams = (pageNum: number, pageSize: number) => {
return {
SkipCount: (pageNum - 1) * pageSize,
MaxResultCount: pageSize,
}
}
// Usage example
const fetchData = async (pageNum: number, pageSize: number) => {
const params = getPagedParams(pageNum, pageSize)
return request.get('/api/v1/data/list', { params })
}
Interface Version Control
// Versioned API call
const apiVersion = 'v1'
const getVersionedRequest = (endpoint: string) => {
return request.get(`/api/${apiVersion}/${endpoint}`)
}
// Usage example
const getData = async () => {
return getVersionedRequest('data')
}
High Frequency Request Throttling
// Throttle wrapper
const createThrottledRequest = (fn: Function, delay: number = 300) => {
let lastCall = 0
return async (...args: any[]) => {
const now = Date.now()
if (now - lastCall < delay) {
return Promise.reject(new Error('Request too frequent'))
}
lastCall = now
return fn(...args)
}
}
// Usage example
const throttledGetData = createThrottledRequest(getData)
Extending Error Handling
// Custom error processor
const handleError = (error: any) => {
switch (error.status) {
case 400:
ElMessage.error('Request parameter error')
break
case 401:
ElMessage.error('Please login first')
break
case 403:
ElMessage.error('Insufficient permission')
break
case 404:
ElMessage.error('Resource not found')
break
default:
ElMessage.error('Network error, please try again later')
}
}
Performance Monitoring Integration
// Request performance monitoring
const monitoredRequest = async (config: any) => {
const startTime = performance.now()
try {
const result = await request(config)
const endTime = performance.now()
console.log(`API ${config.url} took: ${endTime - startTime}ms`)
return result
} catch (error) {
const endTime = performance.now()
console.error(`API ${config.url} failed, took: ${endTime - startTime}ms`)
throw error
}
}
This document comprehensively covers all key aspects of RESTful API integration in the lmes-web-base project, from basic request encapsulation to advanced performance optimization, providing complete technical reference and best practice guidance for developers. Through reasonable architecture design and rich functional features, the system can meet various needs of modern Web applications for API integration.