美文网首页Ajax
fetch.js封装

fetch.js封装

作者: 向艳蓉 | 来源:发表于2021-03-16 15:49 被阅读0次

    npm install whatwg-fetch@3.0.0 --save --dev
    npm install @babel/polyfill@7.4.4 --save --dev
    main.js引入fetch垫片库

    import '@babel/polyfill'; // babel, es6垫片库,ES6语法兼容IE等
    import 'whatwg-fetch'; // fetch垫片库,支持IE等浏览器
    import fetch from './lib/fetch';
    
    /**
      Vue植入$get,$post等方法,并设置默认的请求头
      如果有额外的请求头请如下使用
      Vue.use(fetch[, fixedHeaders: object]);
    */
    Vue.use(fetch);
    

    fetch.js封装

    import { Message } from 'element-ui';
    import { getLocale, getUserId, getToken, urlStringify, getParam } from './util';
    import service from '../service/';
    import i18n from '@/i18n';
    import {
      SERVICE_STATUS_SUCCESS,
      SERVICE_STATUS_TOKEN_FAILED,
      EN_LANG_ID,
      ZH_LANG_ID
    } from '../constants'
    const tips = {
      [ZH_LANG_ID]: {
        tokenError: i18n.t('tokenError'),
        requestError: i18n.t('requestError')
      },
      [EN_LANG_ID]: {
        tokenError: 'Auth error, please refresh the page',
        requestError: 'Request Error'
      }
    }
    const responseStatus200 = 200;
    const mimeJSON = 'application/json';
    const textPlain = 'text/plain';
    let initHeader;
    
    /**
     * 默认请求头
     */
    let defaultHeaders = {
      'X-Emp-No': getUserId(),
      'X-Auth-Value': getToken()
    };
    
    export default {
      install (Vue, headers) {
        Vue.prototype.$get = get;
        Vue.prototype.$post = post;
        Vue.prototype.$put = put;
        Vue.prototype.$del = deleteHttp;
        Vue.prototype.$service = service;
    
        if (typeof headers === 'object') {
          initHeader = headers
        }
      }
    };
    
    /**
     * get请求
     * @param url
     * @param query
     * @param headers
     * @returns {Promise<Response|never>}
     */
    export function get (url, query, headers) {
      return fetch(
        'GET',
        convertUrl(url, query),
        undefined,
        headers
      );
    }
    
    /**
     * post请求
     * @param url
     * @param payload
     * @param headers
     * @returns {Promise<Response|never>}
     */
    export function post (url, payload, headers) {
      return fetch(
        'POST',
        url,
        payload,
        headers
      );
    }
    
    /**
     * put请求
     * @param url
     * @param payload
     * @param headers
     * @returns {Promise<Response|never>}
     */
    export function put (url, payload, headers) {
      return fetch(
        'PUT',
        url,
        payload,
        headers
      );
    }
    
    /**
     * delete请求
     * @param url
     * @param query
     * @param headers
     * @returns {Promise<Response|never>}
     */
    export function deleteHttp (url, query, headers) {
      return fetch(
        'DELETE',
        convertUrl(url, query),
        undefined,
        headers
      );
    }
    
    /**
     * 组合url
     * @param url
     * @param query
     * @returns {*}
     */
    function convertUrl (url, query) {
      if (query) {
        let search;
        switch (typeof query) {
          case 'object':
            search = urlStringify(query);
            break;
          case 'string':
            search = query;
        }
        if (search) {
          url = [url, search].join(url.indexOf('?') === -1 ? '?' : '&');
        }
      }
      return url;
    }
    
    /**
     * 自定义fetch
     * @param method
     * @param url
     * @param body
     * @param headers
     * @returns {Promise<any>}
     */
    export function fetch (method, url, body, headers) {
      if (!url) {
        throw new Error('request url is empty!')
      }
      method = method.toUpperCase();
      // 组合header对象
      headers = headers || {};
      if ((method === 'POST' || method === 'PUT') && !(body instanceof FormData)) {
        headers['Content-Type'] = mimeJSON
        if (typeof body === 'object') {
          body = JSON.stringify(body);
        }
      }
      
      let locale = getLocale();
      headers = Object.assign({ 'X-Lang-Id': locale }, initHeader, headers, defaultHeaders);
      // fetch请求
    
      return new Promise((resolve, reject) => {
         window.fetch(url, {
          method,
          body,
          headers,
          cache: 'no-cache', // 缓存禁用
          mode: 'cors' // 是否支持跨域,可选 no-cors, cors, *same-origin
        }).then(Response => {
          if (Response.status !== responseStatus200) {
            Message({
              message: i18n.t('requestError'),
              type: 'error',
              center: true
            });
            reject(new Error('Response status error'));
            return;
          }
          let resContentType = Response.headers.get('content-type') || mimeJSON;
          if (resContentType.indexOf(mimeJSON) === 0 || resContentType.indexOf(textPlain) === 0) {
            Response.json().then(json => {
              try {
                resolve(responseJson(json, url, locale));
              } catch (e) {
                reject(json);
              }
            })
          } else if (resContentType.indexOf('text/') === 0) {
            Response.text().then(text => resolve(text))
          } else {
            Response.blob().then(blob => {
              resolve(responseBlob(blob, url))
            })
          }
        })
        .catch(() => {
          console.error('fetch catch')
          reject(new Error('fetch catch error'))
        })
      })
    }
    
    /**
     * 处理json
     * @param json
     * @param url
     * @param locale
     * @returns {*}
     */
    function responseJson (json, url, locale) {
      switch (json.code.code) {
        case SERVICE_STATUS_SUCCESS:
          return json.bo;
        case SERVICE_STATUS_TOKEN_FAILED:
          toLogin();
          break;
        default:
          if (json.code.msg) {
            Message({
              message: json.code.msg,
              type: 'error',
              center: true
            });
          }
          throw new Error('fetch error:' + url);
      }
    }
    
    /**
     * 处理blob
     * @param blob
     * @param url
     * @returns {*}
     */
    const filenameReg = /[^/]+$/;
    const urlSplitReg = /[#?]/;
    const illegalCharacter = /[?*:"<>/|]/g;
    function responseBlob (blob, url) {
      return {
        blob,
        download (fileName) {
          if (!fileName) {
            let match = url.split(urlSplitReg)[0].match(filenameReg);
            if (!match) {
              fileName = 'unKnow'
            } else {
              fileName = match[0];
            }
          }
          return downloadBlob(blob, fileName.trim().replace(illegalCharacter, ''));
        }
      }
    }
    
    /**
     * 下载二进制blob
     * @param {blob} blob
     * @param {string} fileName 文件名
     */
    function downloadBlob (blob, fileName) {
      // 兼容IE下载
      if (window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(blob, fileName);
        return;
      }
      const URL = window.URL;
      if (!URL || !URL.createObjectURL) {
        throw new Error('error: not support download blob');
      }
      let a = document.createElement('a');
      let url = URL.createObjectURL(blob);
      a.setAttribute('href', url);
      a.setAttribute('download', fileName);
      a.click();
      URL.revokeObjectURL(url);
    }
    
    export function convertBatchProcessingResult(bo) {
      let successCount = parseInt(bo.success)
      let failCount = parseInt(bo.failed)
      return i18n.t('successProcessPrefix') + successCount + i18n.t('failProcessPrefix') + failCount + i18n.t('batchProcessAlertMsgSuffix')
    }
    
    

    相关文章

      网友评论

        本文标题:fetch.js封装

        本文链接:https://www.haomeiwen.com/subject/huedcltx.html