Implementation approach

  • Encapsulate an Ajax request based on a Promise
  • Add interception and response capabilities
  • Add interrupt request functionality

implementation

Set up the body function

// Request generator
function dispatchResquest (config) {}
function req(config){
    // Define the success and failure callbacks for promise first
    let chain = [dispatchRequest, undefined]
    // If there are request and response interceptors, place interceptors before and after the request generator
    if(config.interceptor){
        chain.unshift(config.interceptor.fulfilled, config.interceptor.rejected)
    }
    if(config.adaptor){
        chain.push(config.adaptor.fulfilled, config.adaptor.rejected)
    }
    let promise = Promise.resolve(config)
    // Promise calls the interceptor, generator, and responder functions in sequence
    while(chain.length){
        promise = promise.then(chain.shift(), chain.shift())
    }
}
Copy the code

Request generator body

function dispatchRequest(config){
    const promise = new Promise((resolve, reject) = > {
        const xhr = new XMLHttpRequest()
        xhr.open(config.method.toUpperCase(), config.url, true)
        xhr.send()
        xhr.timeout = config.timeout
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4) {if(xhr.status === 200) {
                    // Add a timer to the request
                    setTimeout(() = > resolve(xhr.responseText), 5000)}else{
                    reject('request error')}}}})return promise.then(res= > res, reason= > reason)
}
Copy the code

Add abort operation

For the abort operation here, we use a publish subscription

    let call = null
    const mitt = {
        cache: {},
        on(name, func){
            this.cache[name] = func
        },
        emit(name, data){
            this.cache[name] && this.cache[name](data)
        }
    }
    function dispatchRequest(config){
    const promise = new Promise((resolve, reject) = > {
        let xhr = new XMLHttpRequest()
        xhr.open(config.method.toUpperCase(), config.url, true)
        xhr.send()
        xhr.timeout = config.timeout
        // Get the function
        if(config.cancel){
            mitt.emit('abort'.function onCacel(){
                xhr.abort()
                xhr = null
                reject('[abort] request is cancel')
            })
        }
        xhr.onreadystatechange = function(){
            if(xhr.readyState === 4) {if(xhr.status === 200) {
                    // Add a timer to the request
                    setTimeout(() = > resolve(xhr && xhr.responseText), 5000)}else{
                    reject('request error')}}}})return promise.then(res= > res, reason= > reason)
}
function req(config){
    // Define the success and failure callbacks for promise first
    let chain = [dispatchRequest, undefined]
    // If there are request and response interceptors, place interceptors before and after the request generator
    if(config.intercepter){
        chain.unshift(config.intercepter.fulfilled, config.intercepter.rejected)
    }
    if(config.adaptor){
        chain.push(config.adaptor.fulfilled, config.adaptor.rejected)
    }
    if(config.cancel){
    // Store the function
        mitt.on('abort'.function(cancelfunc){
            config.cancel(cancelfunc)
        })
    }
    let promise = Promise.resolve(config)
    // Promise calls the interceptor, generator, and responder functions in sequence
    while(chain.length){
        promise = promise.then(chain.shift(), chain.shift())
    }
}
Copy the code

Finally, call the function

Try it out locally

    req({
        url: 'http://127.0.0.1:5500/1.json'.method: 'GET'.interceptor: {
			fulfilled: e= > {
				console.log('block', e)
				return e
			}
		},
		adaptor: {
			fulfilled: e= > {
				console.log('response', e)
				return e
			}
		},
		cancel(onCancel){
			call = onCancel
		}
    })
    setTimeout(() = > call && call(), 2000)
Copy the code

no problem