preface

  • What do we mean by intercept? Is that we caninterceptAll of them on the pageFetch request, we can ask beforeInterception of request header information, and after the requestInterception results in a server response.
  • What we intercept, we can do with it whatever we want.
  • Interceptor method referenceaxiosThe interceptor method
  • Finally, we’ll also encapsulate operations that are used uniformly on real projects
  • What you need to know
    • Fetch using the FETCH API tutorial
    • Promise tutorial

Realize the principle of

  • Through rewritingfetchMethod, add the functionality we want, and then replacewindowUnder thefetch

For example, the following line of code replaces the native FETCH method

window.fetch = Cfetch
Copy the code

The interceptor implementation of FETCH

The complete code is as follows. The code is annotated in more detail, so I won’t explain it too much

/** * Cfetch * encapsulates interceptor functionality based on native FETCH. Exposed Cfetch uses the same usage as native FETCH, but adds interceptor functionality. Refer to axios' interceptor usage. * Interceptors */

// Define a collection of functions used to store the processing and error result processing of intercepting request and response results
let interceptorsReq = []
let interceptorsReqError = []
let interceptorsRes = []
let interceptorsResError = []

// Copy the method of the native FETCH, we still have to call the native FETCH later, but we do a layer of wrapping on top of the fetch to add the desired functionality
const OriginFetch = window.fetch

function Cfetch(input, init = {}) {
  // interceptorsReq is a collection of interceptor handlers that intercept requests
  interceptorsReq.forEach(item= > {
    init = item(init)
  })

  // Encapsulate a promise around the native FETCH so that the result of the fetch request can be intercepted within the promise.
  // Also, make sure that the Cfetch returns a Promise object.
  return new Promise((resolve, reject) = > {
    // Initiate a fetch request. The fetch request takes the parameters to receive the upper function
    OriginFetch(input, init).then(res= > {
      // interceptorsRes is a collection of intercepting handlers that intercept response results
      interceptorsRes.forEach(item= > {
        // The interceptor processes the response and returns the processed result to the response.
        res = item(res)
      })
      // Resolve the result of interceptor processing
      resolve(res)
    })
      .catch(err= > {
        // interceptorsResError is a collection of intercepting handlers that intercept the result of an error response
        interceptorsResError.forEach(item= > {
        // The interceptor processes the response error and returns the result to the response.
          err = item(err)
        })
        reject(err)
      })
  })
}

// Interceptors provide both request and response interceptors.
// We can bind the two interceptor handlers using the request and response use methods.
The use method takes two arguments, a callback function used as the interceptor's success handler and an errorCallback as an error handler
// The request.use method puts the callback in the interceptorsReq, waiting for execution.
The response.use method puts callback in the interceptorsRes, waiting for execution.
// The interceptor's handler callback receives a single argument.
// The request interceptor callback receives the config before the request is initiated;
// Response The interceptor's callback receives a response from a network request.
const interceptors = {
  request: {
    use(callback, errorCallback) {
      interceptorsReq.push(callback)
      errorCallback && interceptorsReqError.push(errorCallback)
    }
  },
  response: {
    use(callback, errorCallback) {
      interceptorsRes.push(callback)
      errorCallback && interceptorsResError.push(errorCallback)
    }
  }
}

// Expose the export object
export default {
  Cfetch,
  interceptors
}
Copy the code

Cfetch. Interceptors = {} is not an interceptors object, but a Cfetch.

So I’m not going to write it above Cfetch, so they can’t check it out. If the other side has done other counter injection, we can give play to our ideas for another way of thinking injection

Fetch encapsulation use

import { Cfetch, interceptors } from './fetch'
// Here is the JS-cookie library used by my project, mainly to get the token. You can change it to the way you get the token
import Cookies from 'js-cookie'

/** * config User-defined configuration item *@param WithoutCheck does not use the default interface status check and returns response *@param ReturnOrigin returns the entire Response object. False Returns only Response.data *@param ShowError Specifies whether to use the unified error reporting method * for global errors@param CanEmpty Whether the transport argument can be empty *@param Mock Whether to use the mock service *@param Timeout Indicates the timeout period of an interface request. The default value is 10 seconds */
let configDefault = {
  showError: true.canEmpty: false.returnOrigin: false.withoutCheck: false.mock: false.timeout: 10000
}

// Add request interceptor
interceptors.request.use(config= > {
  // Here is the JS-cookie library used by my project, mainly to get the token. You can change it to the way you get the token
  const token = Cookies.get('access_token')
  let configTemp = Object.assign({
    responseType: 'json'.headers: {
      'Content-Type': 'application/json; charset=utf-8'.authorization: `Bearer ${token}`
    },
  }, configDefault, config)
  console.log('Add request interceptor configTemp ==>', configTemp)
  return configTemp
})

// Add a response interceptor
interceptors.response.use(async response => {
  console.log('Intercept response ==>', response)
  console.log('configDefault', configDefault)
  
  // TODO:Here's a copy of the result processing, and there's something you can do here
  const res = await resultReduction(response.clone())

 // HTTP status code 2xx status entry, data.code 200 indicates that the data is correct, no errors
  if (response.status >= 200 && response.status < 300) {
    return response
  } else { // Non-2xx state entry
    if (configDefault.withoutCheck) { // No state detection is performed
      return Promise.reject(response)
    }
    return Promise.reject(response)
  }
})

// The result of the fetch request is a promise
async function resultReduction(response) {
  let res = ' '
  switch (configDefault.responseType) {
    case 'json':
      res = await response.json()
      break
    case 'text':
      res = await response.text()
      break
    case 'blod':
      res = await response.blod()
      break
    default:
      res = await response.json()
      break
  }
  console.log('Result processing', res)
  return res
}

function request(method, path, data, config) {
  letmyInit = { method, ... configDefault, ... config,body: JSON.stringify(data),
  }
  if (method === 'GET') {
    let params = ' '
    if (data) {
    // Object to URL argument
      params = JSON.stringify(data).replace(/:/g.'=')
        .replace(/"/g.' ')
        .replace(/,/g.'&')
        .match(/ \ {([^)] *) \} /) [1]}return Cfetch(`${path}?${params}`, {... configDefault, ... config, }) }return Cfetch(path, myInit)
}

// The get request method uses encapsulation
function get(path, data, config) {
  return request('GET', path, data, config)
}

// The POST request method uses encapsulation
function post(path, data, config) {
  return request('POST', path, data, config)
}

// the put request method uses encapsulation
function put(path, data, config) {
  return request('PUT', path, data, config)
}

// The delete request method uses encapsulation
function del(path, data, config) {
  return request('DELETE', path, data, config)
}

export default {
  fetch: Cfetch,
  get,
  post,
  put,
  delete: del
}

Copy the code

Inject the page and intercept the fetch request for the page

Inject JS code and modify the FETCH method to achieve the function of interceptor. The principle is very simple, that is, we rewrite the FETCH method, add interceptor function to fetch, and then replace the original WINDOe FETCH

window.fetch = Cfetch
Copy the code

The last call

import fetchApi from './fetchApi'

winodw.fetch = fetchApi.fetch

fetchApi.get('http://www.xxx', {id: '1'})

fetchApi.post('http://www.xxx', {id: '1'})
Copy the code

Successful result print as shown below:

Copy the code and start your debugging docking. Any questions, please leave a comment

Reference article:

Native FETCH based encapsulates a FETCH with interceptor functionality, similar to axios’ interceptor

Fetch the API tutorial