/** * Common request methods * support get and post types * file and other types of processing other methods *@param apiUrl
 * @param method  'get' || 'post'
 * @param body  object
 * @param contentType 'json' || ''
 * @returns {Promise<Response | never>}* /
const fetchApi = ( apiUrl, method, body, contentType ) = > {

  if( process.env.NODE_ENV === 'development' ) {
    console.log('Request address ====================', apiUrl);
    console.log('Request parameters ====================', body);
  }
	// requestPath is the public request address
  let url = requestPath + apiUrl ;
  If the parameters are the same, the browser directly uses the cached data. The page is the same as the original page, so a timestamp is added to the request
  body.timeStamp = new Date().getTime();

  const fetchOptions = {}

  fetchOptions.method = method || 'get';
  fetchOptions.credentials = 'include';
  fetchOptions.mode = 'no-cors';

  if (fetchOptions.method === 'get') {
    url = getRequestBodyHandler(url, body)
  }

  if (fetchOptions.method === 'post') {
    // application/json
    if (contentType === 'json') {
      fetchOptions.headers = {
        'Accept': 'application/json'.'Content-Type': 'application/json'
      }
      // The configuration here is to fetch across domains
      fetchOptions.mode = 'cors';
      fetchOptions.cache = 'force-cache';
      
      fetchOptions.body = fetchJsonBodyHandler(body)
    } else { // form data
      fetchOptions.body = postRequestBodyHandler(body)
    }
  }
  return fetch(url, fetchOptions)
    .then(checkServerStatus)
    .then(parseJSON)
    .then(checkServerDataStatus);

}
Copy the code

Description and handling of fetch requests across domains

There are two types of CORS:

  • A simple request

    Some requests do not trigger CORS precheck requests. This article calls such a request a “simple request.” A request is considered a “simple request” if all of the following conditions are met:

    1. Use one of the following methods: GET HEAD POST
    2. The Fetch specification defines a set of header fields that are CORS safe. No header fields other than this set may be set artificially. Accept accept-language content-language content-type DPR Downlink save-data viewport-width Width
    3. Content-type values are one of the following: Application/X-www-form-urlencoded multipart/form-data text/plain
  • CORS with preFlight pre-request

    With preflight CORS, the browser will issue an OPTIONS request, and the server will write in the response whether to allow access to the domain name. Access-control-allow-origin, access-contral-allow-methods, access-Contraol-allow-headers, access-contr are added to the header of response Ol-max-age these fields.

Make a CORS request with credentials

By default, cookies are not sent to the server for cross-domain requests. In the case that cookies need to be sent, xhr.withCredentials = true should be set if XHR is used. The credentials:’include’ need to be set in the request. However, if the server does not return access-Control-allow-crenditials :true, then the server can set the credentials:’include’ in the request. Cookies will not be sent to the server, so pay special attention to the simple GET request, there is no pre-request process, so in the actual request, If the server does not return access-Control-allow-crenditials :true then the browser will not hand the response to the requester.

About the fetch cross-domain illustrate source address: blog.csdn.net/danzhang101…

Actual problems encountered

The latter interface specifies that only POST requests are received, so a FETCH request with a pre-request returns 405. To handle this, add the following configuration to your code:

fetchOptions.mode = 'cors';
fetchOptions.cache = 'force-cache';
Copy the code

Other auxiliary methods

/** * Add json request parameters to the URL *@param url
 * @param ob
 * @returns {*}* /
const getRequestBodyHandler = function (url, ob) {

  if (ob) {

    let param = ' '

    Object.keys(ob).forEach((key, value) = > {
      param ? (param += '&') : (param += '? ')
      param += (key + '=' + ob[key])
    })

    return url + param
  }

  return url

}
Copy the code
/** * Convert json request parameters to formData body * when a POST request is made@param ob
 * @returns {*}* /
const postRequestBodyHandler = function (ob) {

  if (ob) {

    const body = new FormData()

    Object.keys(ob).forEach((key) = > {
      body.append(key, ob[key])
    })

    return body
  }

  return null

}
Copy the code
const fetchJsonBodyHandler = function (ob) {
  return typeof ob === 'object' ? JSON.stringify(ob) : ob
}
Copy the code
/** * Interface data status verification *@param data
 * @returns {*}* /
const checkServerDataStatus = (data) = > {

  if( process.env.NODE_ENV === 'development') {console.log('Request return data ====================', data)
  }
  // Successful return
  if ( data && (data.status === 200 || data.state === 0)) {
    return data.data ;
  }

  // Error handling
  const errorInfoMap = {
    99999: {type: 'dataException'.msg: 'Data exception'
    },
    100000: {
      type: 'unknown'.msg: 'Unknown exception'
    },
    500 : {
      type: 'exception'.msg: 'Interface exception'
    },
    501 : {
      type: 'exception'.msg: 'Interface exception'
    },
    502 : {
      type: 'exception'.msg: 'Interface exception'
    },
    503 : {
      type: 'exception'.msg: 'Interface exception'
    },
    401 : {
      type: 'noPrmission'.msg: 'No access permission'
    },
    403: {
      type: 'refuse'.msg: 'Interface access denied'
    },
    404: {
      type: 'notFound'.msg: 'Interface link does not exist'}}// Error message
  let errorInfo = {
    type: 'unknown'.msg: 'Unknown exception'
  }

  // Error object
  const error = new Error(a);// The data format is abnormal
  if(! data || ! data.status ){Object.assign( error, errorInfo, errorInfoMap[99999]);throw error;
  }

  // Error caught according to code
  let extraErrorInfo = errorInfoMap[ data.status ];
  if( extraErrorInfo ){
    Object.assign( error, errorInfo, extraErrorInfo );
    throw error;
  }

  // Unknown error
  throw error

}
Copy the code
/** * Server request status validation *@param data
 * @returns {*}* /
const checkServerStatus = (response) = > {
  // Request accepted successfully
  if (response.status >= 200 && response.status < 300) {

    return response

  } else {

    // Error handling
    const errorInfoMap = {
      100000: {
        type: 'serverUnknown'.msg: 'Server: Unknown exception'
      },
      502 : {
        type: 'serverMaintainace'.msg: 'Server: Server in maintenance'
      },
      404 : {
        type: 'serverException'.msg: 'Server: access address does not exist'}}// Error message
    let errorInfo = {
      type: 'serverUnknown'.msg: 'Server: Unknown exception'
    }

    // Error object
    const error = new Error(a);// Error caught according to code
    let extraErrorInfo = errorInfoMap[ response.status ];
    if( extraErrorInfo ){
      Object.assign( error, errorInfo, extraErrorInfo );
      throw error;
    }

    // Unknown error
    throw error

  }

}
Copy the code
/ / the json conversion
const parseJSON = (response) = > {
  //response.text() gets the text type
  // Response.json () will help you run json.parse (response.text()) once
  return response.json()
}
Copy the code