For an elegant front end, every brick moved must be elegant and beautiful. Let’s start with request encapsulation. If you use uni, you can use wx. Instead of uni. Will do)

1. Define a deep-copy method for merging parameters in the help module file

// deep merge of JS objects
export function deepMerge( target = {}, source = {} ) {
	target = deepClone( target );
	if ( typeoftarget ! = ='object' || typeofsource ! = ='object' ) return false;
	for ( const prop in source ) {
		if ( !source.hasOwnProperty( prop ) ) continue;
		if ( prop in target ) {
			if ( typeoftarget[ prop ] ! = ='object' ) {
				target[ prop ] = source[ prop ];
			} else {
				if ( typeofsource[ prop ] ! = ='object' ) {
					target[ prop ] = source[ prop ];
				} else {
					if ( target[ prop ].concat && source[ prop ].concat ) {
						target[ prop ] = target[ prop ].concat( source[ prop ] );
					} else{ target[ prop ] = deepMerge( target[ prop ], source[ prop ] ); }}}}else{ target[ prop ] = source[ prop ]; }}return target;
}
Copy the code

2. Define a URL’s regular validation method and place it in the validate module file

/** * Verify the URL format */
export function urlRegExp( value ) {
	return /http(s)? :\/\/([\w-]+\.) +[\w-]+(\/[\w-.\/?%&=]*)? /.test( value )
}
Copy the code

3. Request wrapped code

import {
	deepMerge
} from './help.js'

import {
	urlRegExp
} from './validate.js'

class Http {
	constructor( ) {
		this.config = {
			// The requested root domain name
			baseUrl: ' '.// The default request header
			header: {},
			method: 'POST'.// Set to JSON. Upon return, wx.request will parse the data json.parse
			dataType: 'json'.// No action is required for this parameter
			responseType: 'text'.// Whether loading is enabled by default
			loading: true,}/ / the interceptor
		this.interceptor = {
			// Interception before request
			request: null.// Interception after request
			response: null
		}

		/ / get request
		this.get = ( url, data = {}, loading = this.config.loading, header = {} ) = > {
			return this.request( {
				method: 'GET',
				url,
				header,
				data
			}, loading )
		}

		/ / post request
		this.post = ( url, data = {}, loading = this.config.loading, header = {} ) = > {
			return this.request( {
				url,
				method: 'POST',
				header,
				data
			}, loading )
		}

		/ / put request
		this.put = ( url, data = {}, loading = this.config.loading, header = {} ) = > {
			return this.request( {
				url,
				method: 'PUT',
				header,
				data
			}, loading )
		}

		/ / delete request
		this.delete = ( url, data = {}, loading = this.config.loading, header = {} ) = > {
			return this.request( {
				url,
				method: 'DELETE',
				header,
				data
			}, loading )
		}
	}

	// Set the global default configuration
	create( customConfig ) {
		// Merge objects in depth, otherwise deep attributes of the object will be lost
		this.config = deepMerge( this.config, customConfig );
	}

	// The main request section
	request( options = {}, loading = this.config.loading ) {
		options.loading = loading
		// Check request interception
		if ( this.interceptor.request && typeof this.interceptor.request === 'function' ) {
			let tmpConfig = {};
			let interceptorRequest = this.interceptor.request( options );
			if ( interceptorRequest === false ) {
				// Return a Promise in a pending state to cancel the original Promise and avoid the then() callback
				return new Promise( ( ) =>{}); }this.options = interceptorRequest;
		}
		options.dataType = options.dataType || this.config.dataType;
		options.responseType = options.responseType || this.config.responseType;
		options.url = options.url || ' ';
		options.params = options.params || {};
		options.header = Object.assign( this.config.header, options.header );
		options.method = options.method || this.config.method;

		return new Promise( ( resolve, reject ) = > {
			options.complete = ( response ) = > {
				response.loading = loading
				// Determine whether an interceptor exists
				if ( this.interceptor.response && typeof this.interceptor.response === 'function' ) {
					let resInterceptors = this.interceptor.response( response );
					// If the interceptor does not return false, plug in the then callback directly
					if( resInterceptors ! = =false ) {
						resolve( resInterceptors );
					} else {
						// If the interceptor returns false, it means that the interceptor definer thinks there is a problem with the return and calls the catch callback directlyreject( response.data || response ); }}else {
					// If raw data is required, the original data is returned, even if there is no interceptorresolve( response ); }}// Determine if the URL passed by the user starts with /, if not, add /,
			options.url = urlRegExp( options.url ) ? options.url : ( this.config.baseUrl + ( options.url
				.indexOf( '/') = =0 ?
				options.url : '/'+ options.url ) ); wx.request( options ); }}})export default Http

Copy the code

4. Use Demo: Here we create a new request.js file

Import the HTTP file you just wrapped and configure the request using the request response interceptor

const ACCESS_TOKEN = 'AurhToken' // Key of token certificate

import HTTP from './http.js'
// Create configuration information
const requestConfig = {
	baseUrl: ' '.// https://test.request.api
	timeout: 10 * 1000.// Request timeout
}
// Initialize the request instance
const newHttp = new HTTP( )
newHttp.create( requestConfig )

// Request interception configuration items
const LoadingDelayTime = 750 // showLoading Delay time
let requestNum = 0 // Number of requests
let showLoading = false / / loading condition
let loadingTimer = null // showLoading timer
let RedirectTimer = null // Log in to the timer again

// Request interceptor
newHttp.interceptor.request = config= > {
	/ / add loading
	if ( config.loading ) {
		requestNum++
		Loading is created for the first request in the queue
		if (requestNum === 1) {
			loadingTimer = setTimeout(() = > {
				showLoading = true
				uni.showLoading({
					title: 'loading... '.mask: true
				})
			}, LoadingDelayTime)
		}
	}
        
	// Add Token credentials
	if ( typeofconfig.header ! = ='object' ) config.header = {}
	config.header[ ACCESS_TOKEN ] = 'This is a token content'
        // We can customize the parameters of the request
	// config.data = buildOptions( config.data )
        
	return config
}
// Response interceptor
newHttp.interceptor.response = response= > {
	/ / close the Loading
	if ( response.loading ) {
		requestNum--
		if ( requestNum === 0 ) {
                       if ( loadingTimer ) {
                            clearTimeout( loadingTimer )
                            loadingTimer = null
                        }
			if ( showLoading ) {
                            showLoading = false
                            wx.hideLoading( )
			}
		}
	}
	// All errors are handled uniformly
	if ( response.statusCode === 200 ) {
		const {
			code,
			message
		} = response.data
		switch ( code ) {
			case 0: // Successful response
				return response.data
				break;
			case 401: // Login credentials expire and log in again
                                // Create a timer to prevent multiple requests from returning to 401
				if ( RedirectTimer ) clearTimeout( RedirectTimer )
				RedirectTimer = null
				RedirectTimer = setTimeout( ( ) => {
					wx.showToast( {
						title: Please log in first.icon: 'none'.duration: 1500})let timerS = setTimeout( ( ) => {
						clearTimeout( timerS )
						// Log out
                                                / /...
					}, 1500)},2000 )
				return false
				break;
			default:
				wx.showToast( {
					title: message || 'Network error 1'.icon: 'none'})return false}}else {
		wx.showToast( {
			title: 'Network error 2'.icon: 'none'.duration: 2000})return false}}/ / GET request
export function requestGet( {
	url,
	data = {},
	loading = true,
	header = {}
} ) {
	return newHttp.get( url, data, loading, header )
}
/ / POST request
export function requestPost( {
	url,
	data = {},
	loading = true,
	header = {}
} ) {
	return newHttp.post( url, data, loading, header )
}
/ / PUT request
export function requestPut( {
	url,
	data = {},
	loading = true,
	header = {}
} ) {
	return newHttp.put( url, data, loading, header )
}
/ / DELETE request
export function requestDelete( {
	url,
	data = {},
	loading = true,
	header = {}
} ) {
	return newHttp.delete( url, data, loading, header )
}
Copy the code

tips

Finally is in the small program in each module of the use, in app.js we encapsulated the request method, finally throw ok.

App.js sample code attached:

import { requestGet,requestPost,requestPut,requestDelete } from './utils/request.js'

App({

    $Http: {
        get: requestGet,
        post: requestPost,
        put: requestPut,
        delete: requestDelete
    }
    
})
Copy the code

Request sample code:

// pages/home/home.js
const App = getApp()

page({
    onLoad() {
        this.getDetail()
    },
    getDetail() {
        const params = {
                / / request API
                url: '/api/detail/get'.// Request parameters
                data: {
                    id: 123.type: 1
                },
                // Whether to enable loading. The default value is true
                loading: true 
        }
        App.$Http.post(params).then(res= > {
            // The request succeeded
            console.log(res)
        })
    }
 })

Copy the code