Fetch 是一个现代的概念, 约等同于 XMLHttpRequest,其最大的两个特性:
在Vue 项目开发中,我们与接口打交道最多了,如何来优雅的使用请求变得尤为重要了。 通常我们通过客户端向后端发送HTTP请求来接收接口数据,然后将这些接口数据完美的呈现到网页上。
同时,与接口打交道那么就会用到网络请求,与 Vue 结合的网络请求库有哪些呢?
vue-resource
axios
fetch
本章将使用 fetch 来完成接口的请求,以及对fetch 请求的封装,来满足业务开发。
fetch 是与 XMLHttpRequest同级的方式,而非对ajax的封装。所以在现代浏览器中可以直接使用,无需引用任何库类,低级浏览器中,需要使用降级方案,这点不在我们此次文章之中(IE:你们都看我干什么?)
创建单独文件来封装Fetch,封装的同时,我们需要和 后端 协商好一些约定,如请求头 , 状态码, 等等
同时可以引入必要的UI 提示框, 不同的状态码,提示不同的响应,
请求头 : 来实现一些具体的业务,必须携带一些参数才可以请求(例如:会员业务)
状态码 : 根据接口返回的不同code , 来执行不同的业务,这块需要和后端约定好。
响应拦截器: 这块就是根据 后端 返回来的状态码判定执行不同业务
首先,我们先看一下成品requist结构是什么样的
首先,第一步我们引入了vant的提示框
然后定义了一个 Request class,然后是对于错误请求的error处理,以及对于正确请求的success处理,以及需要业务弹窗错误的businessError处理。最后,是定义一个request对象,并将其export出去
然后我们看一下最核心的,即定义的Request class
class Request {
constructor(parms) {
this.withBaseURL = parms.withBaseURL
this.baseURL = parms.baseURL
}
request(parames) {
let url = parames.url || ''
let method = parames.method || 'GET'
let data = parames.data || ''
this.withBaseURL = (url.indexOf('http') == -1)
let requestUrl = this.withBaseURL ? this.baseURL + url : url;
let options = {
method,
credentials: 'include',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(data)
}
if (method == 'GET') {
delete options.body;
let qs = '?';
for (const key in parames.data) {
qs += key + '=' + parames.data[key] + '&'
}
qs = qs.substring(0, qs.length - 1)
qs.length > 1 ? requestUrl += qs : ''
}
return fetch(requestUrl, options)
.then(function (response) {
return response.json();
})
.then(function (res) {
return successFn(res)
}).catch(function (err) {
error(err)
})
}
}
在class 中,我们定义了一个构造函数,其接收一个对象,用于控制request的白名单与请求前缀,然后是其关键的request方法,这个方法也接受一个JSON,对象默认三个属性,分别是请求url,method,以及需要传递的参数
白名单用不是核心,我这里定义的白名单是为了处理不属于同一个后端的请求,如果你的项目中没有,可以不定义。
options是为了配置对于请求fetch控制不同配置的 init 对象:
对于get请求,需要一些特殊的处理,fetch中,get不可以放置body,其次参数需要拼接在url之后。
最后,我们定义一个fetch请求,将我们处理好的参数放置进去,随后,使用successFn作为响应拦截器。error作为网络错误的处理函数。
这样,我们对于request的封装基本已经完成了,完整代码如下
/*
* @Author: WJK
* @Date: 2020-03-01 13:21:27
* @LastEditTime: 2020-03-02 13:10:41
*/
import { Toast } from 'vant';
class Request {
constructor(parms) {
this.withBaseURL = parms.withBaseURL
this.baseURL = parms.baseURL
}
request(parames) {
let url = parames.url || ''
let method = parames.method || 'GET'
let data = parames.data || ''
this.withBaseURL = (url.indexOf('http') == -1)
let requestUrl = this.withBaseURL ? this.baseURL + url : url;
let options = {
method,
credentials: 'include',
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: JSON.stringify(data)
}
if (method == 'GET') {
delete options.body;
let qs = '?';
for (const key in parames.data) {
qs += key + '=' + parames.data[key] + '&'
}
qs = qs.substring(0, qs.length - 1)
qs.length > 1 ? requestUrl += qs : ''
}
return fetch(requestUrl, options)
.then(function (response) {
return response.json();
})
.then(function (res) {
return successFn(res)
}).catch(function (err) {
error(err)
})
}
}
function error(err) {
Toast({
message: '网络不给力!请稍后再试',
icon: 'none',
duration: 3500
})
}
function successFn(data) {
switch (data.code) {
case 0:
return data.data
break;
default:
businessError(data.msg)
break;
}
}
function businessError(params) {
Toast({
message: params,
duration: 2000
})
}
const request = new Request({
baseURL: process.env.VUE_APP_API,
withBaseURL: true
})
export default request
封装了之后,接下来就是如何使用,我们可以将项目中所有的请求,集中在一个api.js中进行处理,当需要调用的时候,可以直接引用使用
代码如下:
import request from './request'
let publicurl = '/'
/**
* @msg: 获取首页数据
* @param {type}
* @return:
*/
export function index(data) {
return request.request({
url: `${publicurl}front/index`,
method: 'POST',
data,
})
}
将request对象引用进来,使用的时候,直接调用方法即可,publicurl用于放置统一请求前缀,method中用于放置请求类型,data中用于放置请求参数。
最后,当我们需要调用这个请求的时候,可以在vue中使用
import { index } from "@/apis/index";
//调用
index({ json: "" })
.then()
.catch();