vue项目中使用fetch的实现方法


Posted in Javascript onApril 25, 2019

fetch的由来和定义

fetch的由来     

众所周知,传统 Ajax (指 XMLHttpRequest)是最早出现的发送异步请求技术,其核心是使用XMLHttpRequest对象。但是它也存在一些令人头疼的问题:XHR 是一个设计粗糙的 API,不符合关注分离的原则;配置和调用方式非常混乱,而且基于事件的异步模型写起来也没有现代的 Promise,generator/yield,async/await 友好。而Fetch 的出现就是为了解决 XHR 存在的问题。

fetch的定义和使用

MDN中的描述:  

Fetch API 提供了一个获取资源的接口(包括跨域请求)。任何使用过 XMLHttpRequest 的人都能轻松上手,但新的API提供了更强大和灵活的功能集。but 因为凄惨的兼容性,让这个东东用起来比较困难。那我可以自己封装一下,对于不支持fetch的浏览器便使用ajax 代替(见下文)。      

Fetch 的核心在于对 HTTP 接口的抽象,包括 Request,Response,Headers,Body,以及用于初始化异步请求的 global fetch。其中,global fetch方法的语法定义:

fetch(input[, init]); 

input:定义要获取的资源。可以是一个资源的 URL 字符串,也可以是一个 Request 对象。
init:可选,一个配置项对象,包括所有对请求的设置。包括:method,headers,body,mode,credentials等返回值:Promise     

切记一点:Fetch是基于promise设计的,它不是ajax的进一步封装,而是原生js API,没有使用XMLHttpRequest对象。

fetch的优点和缺点

优点:

1. 语法简洁,更加语义化
2. 基于标准 Promise 实现,支持 async/await
3. 同构方便,更加底层,提供的API丰富(request, response, body , headers)5. 脱离了XHR,是ES规范里新的实现方式

缺点:

1. fetch只对网络请求报错,对400,500都当做成功的请求,服务器返回 400,500 错误码时并不会 reject。
2. fetch默认不会带cookie,需要添加配置项: credentials: 'include'。
3. fetch不支持abort,不支持超时控制,造成了流量的浪费。
4. fetch没有办法原生监测请求的进度,而XHR可以

补充知识点:

Fetch的mode配置项有3个取值:   

same-origin:该模式是不允许跨域的,它需要遵守同源策略;   

cors: 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;

no-cors: 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;目前,针对跨域请求,cors模式是常见的实现。

vue项目中完美封装fetch

话不多少,直接附上代码。

env.js文件,如下:

/** 
* baseUrl: 域名地址 
* routerMode: 路由模式
*/

let baseUrl = '';
let routerMode = 'history';
if (process.env.NODE_ENV == 'development') { 
  baseUrl = 'http://localhost:3000';
}else{ 
  baseUrl = 'http://xxxx这里是线上地址xxx';
}

export { baseUrl, routerMode }

fetch.js文件,如下:

import { baseUrl } from './env'
export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {
 type = type.toUpperCase();
 url = baseUrl + url;

    // 此处规定get请求的参数使用时放在data中,如同post请求
 if (type == 'GET') {
 let dataStr = ''; 
 Object.keys(data).forEach(key => {
  dataStr += key + '=' + data[key] + '&';
 })
 
 if (dataStr !== '') {
  dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
  url = url + '?' + dataStr;
 }
 }

    // 对于支持fetch方法的浏览器,处理如下:
 if (window.fetch && method == 'fetch') {
 let requestConfig = {
            // fetch默认不会带cookie,需要添加配置项credentials允许携带cookie
  credentials: 'include', 
  method: type,
  headers: {
  'Accept': 'application/json',
  'Content-Type': 'application/json'
  },
  mode: "cors", // 以CORS的形式跨域
  cache: "force-cache"
 }
 
 if (type == 'POST') {
  Object.defineProperty(requestConfig, 'body', {
  value: JSON.stringify(data)
  })
 }
 
 try {
  const response = await fetch(url, requestConfig);
  const responseJson = await response.json();
  return responseJson
 } catch (error) {
  throw new Error(error)
 }
 } else { // 对于不支持fetch的浏览器,便自动使用 ajax + promise
 return new Promise((resolve, reject) => {
  let requestObj;
  if (window.XMLHttpRequest) {
  requestObj = new XMLHttpRequest();
  } else {
  requestObj = new ActiveXObject; // 兼容IE
  }
 
  let sendData = '';
  if (type == 'POST') {
  sendData = JSON.stringify(data);
  }
 
  requestObj.open(type, url, true);
  requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  requestObj.send(sendData);
 
  requestObj.onreadystatechange = () => {
  if (requestObj.readyState == 4) {
   if (requestObj.status == 200) {
   let obj = requestObj.response
   if (typeof obj !== 'object') {
    obj = JSON.parse(obj);
   }
   resolve(obj)
   } else {
   reject(requestObj)
   }
  }
  }
 })
 }
}

以上代码,亲测有效。Over, thanks !希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
原生js实现日期联动
Jan 12 Javascript
js+css实现超简洁的二级下拉菜单效果代码
Sep 07 Javascript
JavaScript Math 对象常用方法总结
Apr 28 Javascript
简单实现jQuery进度条轮播实例代码
Jun 20 Javascript
基于复选框demo(分享)
Sep 27 Javascript
JS设计模式之状态模式概念与用法分析
Feb 05 Javascript
微信小程序实现顶部导航特效
Jan 28 Javascript
深入理解使用Vue实现Context-Menu的思考与总结
Mar 09 Javascript
javascript canvas API内容整理
Feb 16 Javascript
Node Mongoose用法详解【Mongoose使用、Schema、对象、model文档等】
May 13 Javascript
JS实现小米轮播图
Sep 21 Javascript
关于antd tree 和父子组件之间的传值问题(react 总结)
Jun 02 Javascript
详解vuejs2.0 select 动态绑定下拉框支持多选
Apr 25 #Javascript
微信小程序遍历Echarts图表实现多个饼图
Apr 25 #Javascript
在微信小程序中使用图表的方法示例
Apr 25 #Javascript
详解VUE Element-UI多级菜单动态渲染的组件
Apr 25 #Javascript
WebGL three.js学习笔记之阴影与实现物体的动画效果
Apr 25 #Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
Apr 25 #Javascript
Angular封装搜索框组件操作示例
Apr 25 #Javascript
You might like
PHP实现时间比较和时间差计算的方法示例
2017/07/24 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
2017/08/28 PHP
Laravel利用gulp如何构建前端资源详解
2018/06/03 PHP
jquery 操作表格实现代码(多种操作打包)
2011/03/20 Javascript
理清apply(),call()的区别和关系
2011/08/14 Javascript
jquery如何判断某元素是否具备指定的样式
2013/11/05 Javascript
js整数字符串转换为金额类型数据(示例代码)
2013/12/26 Javascript
js几秒以后倒计时跳转示例
2013/12/26 Javascript
基于javascript实现的快速排序
2016/12/02 Javascript
jQuery简介_动力节点Java学院整理
2017/07/04 jQuery
基于Bootstrap框架菜鸟入门教程(推荐)
2017/09/17 Javascript
vue.js做一个简单的编辑菜谱功能
2018/05/08 Javascript
js实现弹出框的拖拽效果实例代码详解
2019/04/16 Javascript
Vue-CLI项目中路由传参的方式详解
2019/09/01 Javascript
Vue 中使用富文本编译器wangEditor3的方法
2019/09/26 Javascript
Vue循环遍历选项赋值到对应控件的实现方法
2020/06/22 Javascript
[02:10]DOTA2亚洲邀请赛 EG战队出场宣传片
2015/02/07 DOTA
浅谈Python的文件类型
2016/05/30 Python
Python做文本按行去重的实现方法
2016/10/19 Python
Python 确定多项式拟合/回归的阶数实例
2018/12/29 Python
pandas.DataFrame的pivot()和unstack()实现行转列
2019/07/06 Python
Python操作MySQL数据库实例详解【安装、连接、增删改查等】
2020/01/17 Python
解决启动django,浏览器显示“服务器拒绝访问”的问题
2020/05/13 Python
Python命名空间namespace及作用域原理解析
2020/06/05 Python
详解Python yaml模块
2020/09/23 Python
使用CSS3实现input多选框自定义样式的方法示例
2019/07/19 HTML / CSS
唤醒头发毛囊的秘密武器:Grow Gorgeous
2016/08/28 全球购物
德国家具、照明、家居用品网上商店:Wayfair.de
2020/02/13 全球购物
统计学专业毕业生的自我评价分享
2013/11/28 职场文书
2014端午节活动策划方案
2014/01/27 职场文书
期末自我鉴定
2014/02/02 职场文书
公司领导班子对照材料
2014/08/18 职场文书
2015年度党员自我评价范文
2015/03/03 职场文书
个人年度总结报告
2015/03/09 职场文书
2017年寒假少先队活动总结
2016/04/06 职场文书
Promise面试题详解之控制并发
2021/05/14 面试题