fetch.js封装

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')
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,470评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,393评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,577评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,176评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,189评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,155评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,041评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,903评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,319评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,539评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,703评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,417评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,013评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,664评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,818评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,711评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,601评论 2 353

推荐阅读更多精彩内容