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 调整select 位置的函数
Feb 21 Javascript
使用Grunt.js管理你项目的应用说明
Apr 24 Javascript
javascript获取下拉列表框当中的文本值示例代码
Jul 31 Javascript
js实现宇宙星空背景效果的方法
Mar 03 Javascript
JS实现slide文字框缩放伸展效果代码
Nov 05 Javascript
AngularJs实现分页功能不带省略号的代码
May 30 Javascript
Node.js DES加密的简单实现
Jul 07 Javascript
self.attachevent is not a function的解决方法
Apr 04 Javascript
vue+axios新手实践实现登陆的示例代码
Jun 06 Javascript
JS实现联想、自动补齐国家或地区名称的功能
Jul 07 Javascript
vuejs实现下拉框菜单选择
Oct 23 Javascript
JavaScript实现登录窗体
Jun 22 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
第4章 数据处理-php数组的处理-郑阿奇
2011/07/04 PHP
在Nginx上部署ThinkPHP项目教程
2015/02/02 PHP
Zend Framework教程之配置文件application.ini解析
2016/03/10 PHP
iOS自定义提示弹出框实现类似UIAlertView的效果
2016/11/16 PHP
PHP实现数组的笛卡尔积运算示例
2017/12/15 PHP
PHP设计模式之装饰器模式实例详解
2018/02/07 PHP
phpinfo无法显示的原因及解决办法
2019/02/15 PHP
php实现对短信验证码发送次数的限制实例讲解
2021/03/04 PHP
JavaScript Cookie 直接浏览网站分网址
2009/12/08 Javascript
jQuery学习3:操作元素属性和特性
2010/02/07 Javascript
js播放wav文件(源码)
2013/04/22 Javascript
jquery动态加载select下拉框示例代码
2013/12/10 Javascript
Jquery 点击按钮自动高亮实现原理及代码
2014/04/25 Javascript
点击A元素触发B元素的事件在IE8下会识别成A元素
2014/09/04 Javascript
JS实现判断碰撞的方法
2015/02/11 Javascript
javascript操作表格排序实例分析
2015/05/06 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
JS+CSS实现仿支付宝菜单选中效果代码
2015/09/25 Javascript
jQuery学习心得总结(必看篇)
2016/06/10 Javascript
EasyUI 结合JS导出Excel文件的实现方法
2016/11/10 Javascript
vue双向数据绑定原理探究(附demo)
2017/01/17 Javascript
jQuery日期范围选择器附源码下载
2017/05/23 jQuery
微信小程序蓝牙连接小票打印机实例代码详解
2019/06/03 Javascript
python 查找文件夹下所有文件 实现代码
2009/07/01 Python
Python import用法以及与from...import的区别
2015/05/28 Python
Python实现列表转换成字典数据结构的方法
2016/03/11 Python
Python实现的查询mysql数据库并通过邮件发送信息功能
2018/05/17 Python
python3实现字符串的全排列的方法(无重复字符)
2018/07/07 Python
Django框架中间件(Middleware)用法实例分析
2019/05/24 Python
Python装饰器原理与基本用法分析
2020/01/07 Python
python利用appium实现手机APP自动化的示例
2021/01/26 Python
css3 media 响应式布局的简单实例
2016/08/03 HTML / CSS
《守株待兔》教学反思
2014/03/01 职场文书
2014年出纳工作总结与计划
2014/12/09 职场文书
金秋助学感谢信
2015/01/21 职场文书
CSS极坐标的实例代码
2021/06/03 HTML / CSS