Fetch
Fetch API 提供了一个 JavaScript 接口,用于拜访和操纵 HTTP 管道的一些具体局部,例如申请和响应。
它还提供了一个全局 fetch() 办法,该办法提供了一种简略,正当的形式来跨网络异步获取资源。
这种性能以前是应用 XMLHttpRequest 实现的。
Fetch 提供了一个更现实的代替计划,能够很容易地被其余技术应用,例如 Service Workers。
Fetch 还提供了 专门的逻辑空间来定义其余与 HTTP 相干的概念,例如 CORS 和 HTTP 的扩大。
请留神,fetch 标准 与 jQuery.ajax() 次要有以下的不同:
- 当接管到一个代表谬误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即便响应的 HTTP 状态码是 404 或 500。相同,它会 将 Promise 状态标记为 resolve(如果响应的 HTTP 状态码不在 200 – 299 的范畴内,则设置 resolve 返回值的 ok 属性为 false),仅当
网络故障
时或申请被阻止
时,才会标记为 reject。 - fetch 不会发送跨域 cookie,除非你应用了 credentials 的初始化选项。
一个根本的 fetch 申请设置起来很简略。看看上面的代码:
fetch('http://example.com/movies.json')
.then(response => response.json())
.then(data => console.log(data));
参考 fetch(),查看所有可选的配置和更多形容。
// Example POST method implementation:
async function postData(url = '', data = {}) {
// Default options are marked with *
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects}
postData('https://example.com/answer', { answer: 42})
.then(data => {console.log(data); // JSON data parsed by `data.json()` call});
留神:mode: “no-cors” 仅容许应用一组无限的 HTTP 申请头:
- Accept
- Accept-Language
- Content-Language
- Content-Type 容许应用的值为:application/x-www-form-urlencoded、multipart/form-data 或 text/plain
MDN 地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Us…
qs 简介
一个带有一些附加 安全性 的查问字符串解析 和字符串化 库。
次要维护者:Jordan Harband
最后创建者和维护者:TJ Holowaychuk
npmjs 仓库地址:https://www.npmjs.com/package/qs
react 应用 qs
装置
npm install qs
import qs from'qs'
qu.stringify()和 qs.parse()
- qu.stringify() : 将
对象序列化成 url 的模式
;以&
进行拼接 - qs.parse(): 将 url 解析成对象模式;
1、qs.parse() 将 URL 解析成对象的模式
import Qs from 'qs';
let url = 'method=query_sql_dataset_d<a style="color:transparent"> 起源 gao*daima.com 搞 @代 #码网 </a>ata&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0';
Qs.parse(url);
console.log(Qs.parse(url));
输入后果
{
method:'query_sql_dataset_data',
projectId:'85',
appToken:'7d22e38e-5717-11e7-907b-a6006ad3dba0'
}
2、qs.stringify()将对象序列化成 URL 的模式,以 & 进行拼接(可用于发送查问条件)
import Qs from 'qs';
let obj= {
method: "query_sql_dataset_data",
projectId: "85",
appToken: "7d22e38e-5717-11e7-907b-a6006ad3dba0",
datasetId: "12564701"
};
Qs.stringify(obj);
console.log(Qs.stringify(obj));
输入的是:
method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0&datasetId=%12564701
JSON.stringify(param) VS Qs.stringify(param),
JSON 中同样存在 stringify办法,然而和 Qs.stringify 之间的区别是很显著的
// JSON.stringify(param)
{"uid":"cs11","pwd":"000000als","username":"cs11","password":"000000als"}
// Qs.stringify(param)
uid=cs11&pwd=000000als&username=cs11&password=000000als
封装 fetch
为什么封装 Fetch 申请
- 申请的中央代码更少。
- 公共的谬误对立一个中央增加即可。
- 申请定制的谬误还是申请本人也能够解决。
- 扩展性好,增加性能只须要改一个中央。
总结起来一句话:简略,好用
封装 Fetch 申请(次要文件)
“./fetchUtil”
import qs from 'qs';
import {message} from 'antd';
const {stringify, parse} = qs;
const checkStatus = res => {if (200 >= res.status < 300) {return res;}
message.error(` 网络申请失败,${res.status}`);
const error = new Error(res.statusText);
error.response = error;
throw error;
};
/**
* 捕捉胜利登录过期状态码等
* @param res
* @returns {*}
*/
const judgeOkState = async res => {const cloneRes = await res.clone().json();
//TODO: 能够在这里管控全局申请
if (!!cloneRes.code && cloneRes.code !== 200) {message.error(`11${cloneRes.msg}${cloneRes.code}`);
}
return res;
};
/**
* 捕捉失败
* @param error
*/
const handleError = error => {if (error instanceof TypeError) {message.error(` 网络申请失败啦!${error}`);
}
return { // 避免页面解体,因为每个接口都有判断 res.code 以及 data
code: -1,
data: false,
};
};
class http {
/**
* 动态的 fetch 申请通用办法
* @param url
* @param options
* @returns {Promise<unknown>}
*/
static async staticFetch(url = '', options = {}) {
const defaultOptions = {
/* 容许携带 cookies*/
credentials: 'include',
/* 容许跨域 **/
mode: 'cors',
headers: {
token: null,
Authorization: null,
// 当申请办法是 POST,如果不指定 content-type 是其余类型的话,默认为如下,要求参数传递款式为 key1=value1&key2=value2,但理论场景以 json 为多
// 'content-type': 'application/x-www-form-urlencoded',
},
};
if (options.method === 'POST' || 'PUT') {defaultOptions.headers['Content-Type'] = 'application/json; charset=utf-8';
}
const newOptions = {...defaultOptions, ...options};
console.log('newOptions', newOptions);
return fetch(url, newOptions)
.then(checkStatus)
.then(judgeOkState)
.then(res => res.json())
.catch(handleError);
}
/**
*post 申请形式
* @param url
* @returns {Promise<unknown>}
*/
post(url, params = {}, option = {}) {const options = Object.assign({ method: 'POST'}, option);
// 个别咱们罕用场景用的是 json,所以须要在 headers 加 Content-Type 类型
options.body = JSON.stringify(params);
// 能够是上传键值对模式,也能够是文件,应用 append 发明键值对数据
if (options.type === 'FormData' && options.body !== 'undefined') {let params = new FormData();
for (let key of Object.keys(options.body)) {params.append(key, options.body[key]);
}
options.body = params;
}
return http.staticFetch(url, options); // 类的静态方法只能通过类自身调用
}
/**
* put 办法
* @param url
* @returns {Promise<unknown>}
*/
put(url, params = {}, option = {}) {const options = Object.assign({ method: 'PUT'}, option);
options.body = JSON.stringify(params);
return http.staticFetch(url, options); // 类的静态方法只能通过类自身调用
}
/**
* get 申请形式
* @param url
* @param option
*/
get(url, option = {}) {const options = Object.assign({ method: 'GET'}, option);
return http.staticFetch(url, options);
}
}
const requestFun = new http(); //new 生成实例
export const {post, get, put} = requestFun;
export default requestFun;
定义接口文件,导出 fetch
utils/api
import requestFun from "./fetchUtil"; // 引入
import qs from "qs";
const {stringify} = qs;
const {post, get} = requestFun;
//get 形式
export async function fetchData1(params) {return get(`/api/bbb?${stringify(params)}`);
}
//post 形式
export async function fetchData2(params) {return post(`/api/aaa`, params);
}
export async function fetchGetComments(params) {return get(`http://localhost:8001/comments`, params);
}
组件内应用
home.js
import {fetchGetComments} from '../../utils/api'
// 获取数据
const loadData = async ()=> {const commentData = await fetchGetComments();
console.log('commentData')
console.log(commentData)
}
延申问题
如果要扩大 fetch 的 delete 和 patch,该如何做?
如果自定义 header 的话,该如何做?
如果 post 后端须要 formdata 构造数据又该如何做?
感兴趣的小伙伴,能够自行脑补一下。
参考文档
- https://www.jianshu.com/p/a6573cd68ae6