使用XHR发送一个json请求一般是这样:

 const xhr = new XMLHttpRequest()
xhr.open('Get', url)
xhr.responseType = 'json' xhr.onload = () => {
console.log(xhr.response)
} xhr.onerror = () => {
console.log('error')
} xhr.send()

使用fetch的实例:

 fetch(url).then(response => response.json())
.then(data => console.log(data))
.catch(e => console.log('error', e))

Fetch参数

fetch(input [,init])

input(必须) 定义要获取的资源(请求地址)

init(可选)

参数 | 描述

method   请求使用的方法,如GET、POST

headers   http请求头(user-Agent, Cookie)

body   请求的body信息

mode

fetch可以设置不同的模式使得请求有效. 模式可在fetch方法的第二个参数对象中定义.

可定义的模式如下:

  • same-origin: 表示同域下可请求成功; 反之, 浏览器将拒绝发送本次fetch, 同时抛出错误 “TypeError: Failed to fetch(…)”.
  • cors: 表示同域和带有CORS响应头的跨域下可请求成功. 其他请求将被拒绝.
  • cors-with-forced-preflight: 表示在发出请求前, 将执行preflight检查.
  • no-cors: 常用于跨域请求不带CORS响应头场景, 此时响应类型为 “opaque”.

除此之外, 还有两种不太常用的mode类型, 分别是 navigate , websocket , 它们是 HTML标准 中特殊的值, 这里不做详细介绍.

credentials

 omit(缺省值,默认为该值)、same-origin(同源,便是同域请求才发送cookie)、include(任何请求都带cookie)

cache

  • default(表示fetch请求之前将检查下http的缓存)
  • no-store(表示fetch请求将完全忽略http缓存的存在,这意味着请求之前将不再检查下http的缓存, 拿到响应后, 它也不会更新http缓存)
  • no-cache(如果存在缓存,那么fetch将发送一个条件查询request和一个正常的request, 拿到响应后,它会更新http缓存)
  • reload(表示fetch请求之前将忽略http缓存的存在, 但是请求拿到响应后,它将主动更新http缓存)
  • force-cache(表示fetch请求不顾一切的依赖缓存, 即使缓存过期了,它依然从缓存中读取. 除非没有任何缓存, 那么它将发送一个正常的request)
  • only-if-cached(表示fetch请求不顾一切的依赖缓存, 即使缓存过期了,它依然从缓存中读取. 如果没有缓存, 它将抛出网络错误(该设置只在mode为”same-origin”时有效).

如果fetch请求的header里包含 If-Modified-Since, If-None-Match, If-Unmodified-Since, If-Match, 或者 If-Range 之一, 且cache的值为 default , 那么fetch将自动把 cache的值设置为 "no-store"

 Fetch - response type

一个fetch请求的相应类型(response.type)为如下三种之一:

  • baisc (同域下,相应类型为basic)
  • cors (同样是跨域下, 如果服务器返回了CORS响应头, 那么响应类型将为 “cors”. 此时响应头中除 Cache-Control , Content-Language , Content-Type , Expores , Last-Modified 和 Progma 之外的字段都不可见.)
  • opaque ( 跨域下, 服务器没有返回CORS响应头, 响应类型为 “opaque”. 此时我们几乎不能查看任何有价值的信息, 比如不能查看response, status, url等等等等.)

注意: 无论是同域还是跨域, 以上 fetch 请求都到达了服务器.

 Fetch 常见坑

  1.Fetch 请求默认是不带 cookie 的,需要设置 fetch(url, {credentials: 'include'})

    默认情况下, fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头)

  2.服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。

    当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 reolve 的返回值的 ok 属性设置为 false, 想要精确判断fetch()是否成功,需要包含 promise resolved 的情况,此时再判断 Response.ok 是不是为 true。HTTP状态码为200-299是才会设置为true), 仅当网络故障时或请求被阻止时,才会标记为 rejec

使用Fetch封装request方法

http.js

 import 'whatwg-fetch';

 const netErrorStatu = 1;    // 网络错误
const serverErrorStatu = 2; // 服务器错误
const formatErrorStatu = 3; // 数据格式错误
const logicErrorStatu = 4; // 业务逻辑错误 const errorMsg = {
[netErrorStatu]: '网络错误',
[serverErrorStatu]: '服务器错误',
[formatErrorStatu]: '数据格式错误',
[logicErrorStatu]: '业务逻辑错误'
}; class CustomFetchError {
constructor(errno, data) {
this.errno = errno;
this.msg = errorMsg[errno];
this.data = data;
}
} export function buildQuery(data) {
const toString = Object.prototype.toString; const res = Object.entries(data).reduce((pre, [key, value]) => {
let newValue; if (Array.isArray(value) || toString.call(value) === '[object Object]') {
newValue = JSON.stringify(value);
} else {
newValue = (value === null || value === undefined) ? '' : value;
} pre.push(`${key}=${encodeURIComponent(newValue)}`); return pre;
}, []); return res.join('&');
} export async function request(input, opt) {
// 设置请求默认带cookie
const init = Object.assign({
credentials: 'include'
}, opt); let res;
// 仅当网络故障时或请求被阻止时,才会标记为 rejec
try {
res = await fetch(input, init);
} catch (e) {
throw new CustomFetchError(netErrorStatu, e);
}
// 仅HTTP状态码为200-299是才会设置为true
if (!res.ok) {
throw new CustomFetchError(serverErrorStatu, res);
} let data;
// fetch()请求返回的response是Stream对象,调用response.json时由于异步读取流对象所以返回的是一个Promise对象
try {
data = await res.json();
} catch (e) {
throw new CustomFetchError(formatErrorStatu, e);
}
// 根据和后台的约定设置的错误处理
if (!data || data.errno !== 0) {
throw new CustomFetchError(logicErrorStatu, data);
} return data.data;
} export function get(url, params = {}, opt = {}) {
const init = Object.assign({
method: 'GET'
}, opt); // ajax cache
Object.assign(params, {
timestamp: new Date().getTime()
}); const paramsStr = buildQuery(params); const urlWithQuery = url + (paramsStr ? `?${paramsStr}` : ''); return request(urlWithQuery, init);
} export function post(url, params = {}, opt = {}) {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}; const init = Object.assign({
method: 'POST',
body: buildQuery(params),
headers
}, opt); return request(url, init);
} export default {
request,
get,
post
};

requset.js

 import { notification } from 'antd';
import Loading from 'components/Loading';
import { LOGIN_URL } from 'constants/basic';
import * as http from './http'; const loading = Loading.newInstance(); async function request(method, url, params, opt = {}, httpOpt) {
/**
* needLoading 是否添加loading图片
* checkAccount 验证未登陆是否跳登陆页面
* showErrorMsg 是都显示通用错误提示
*/
const {
needLoading = true,
checkAccount = true,
showErrorMsg = true
} = opt; if (needLoading) {
loading.add();
} let res; try {
res = await http[method](url, params, httpOpt);
} catch (e) {
if (checkAccount && e.errno === 4 && e.data.errno === 10000) {
location.href = LOGIN_URL;
} if (showErrorMsg) {
notification.error({
message: '提示信息',
description: e.errno === 4 ? e.data.msg : e.msg
});
} throw e;
} finally {
if (needLoading) {
loading.remove();
}
} return res;
} export function get(...arg) {
return request('get', ...arg);
} export function post(...arg) {
return request('post', ...arg);
}

  github的代码地址: https://github.com/haozhaohang/library

fetch知识点汇总的更多相关文章

  1. nginx几个知识点汇总

    WHY? 为什么用Nginx而不用LVS? 7点理由足以说明一切:1 .高并发连接: 官方测试能够支撑 5 万并发连接,在实际生产环境中跑到 2 - 3 万并发连接数.?2 .内存消耗少: 在 3 万 ...

  2. python全栈开发 * 10知识点汇总 * 180612

    10 函数进阶 知识点汇总 一.动态参数 形参的第三种1.动态接收位置传参 表达:*args (在参数位置编写 * 表⽰接收任意内容) (1)动态位置参数def eat(*args): print(a ...

  3. 清华大学OS操作系统实验lab1练习知识点汇总

    lab1知识点汇总 还是有很多问题,但是我觉得我需要在查看更多资料后回来再理解,学这个也学了一周了,看了大量的资料...还是它们自己的80386手册和lab的指导手册觉得最准确,现在我就把这部分知识做 ...

  4. c++ 函数知识点汇总

    c++ 函数知识点汇总 swap函数 交换两个数组元素 比如 swap(a[i],a[j]); 就是交换a[i] 和 a[j] 的值 strcpy() 复制一个数组元素的值到另一个数组元素里 strc ...

  5. 前端开发 JavaScript 干货知识点汇总

    很多初学的朋友经常问我,前端JavaScript都需要学习哪些东西呀?哪些是JavaScript的重点知识啊? 其实做前端开发工程师,所有的知识点都是我们学习必备的东西,只有扎实的技术基础才是高薪的关 ...

  6. BBS项目知识点汇总

    目录 bbs项目知识点汇总 一. JavaScript 1 替换头像 2 form表单拿数据 3 form组件error信息渲染 4 添加html代码 5 聚焦操作 二 . html在线编辑器 三 . ...

  7. Java面试知识点汇总

    Java面试知识点汇总 置顶 2019年05月07日 15:36:18 温柔的谢世杰 阅读数 21623 文章标签: 面经java 更多 分类专栏: java 面试 Java面试知识汇总   版权声明 ...

  8. 离散数学 II(最全面的知识点汇总)

    离散数学 II(知识点汇总) 目录 离散数学 II(知识点汇总) 代数系统 代数系统定义 例子 二元运算定义 运算及其性质 二元运算的性质 封闭性 可交换性 可结合性 可分配性 吸收律 等幂性 消去律 ...

  9. ECMAScript版本知识点汇总

    ECMAScript版本知识点汇总 ES5 btoa.atob 对参数进行base64格式编码.解码 /** * btoa() * base64编码 * @param {string} str * @ ...

随机推荐

  1. NOIP2012疫情控制(二分答案+倍增+贪心)

    Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...

  2. LINUX 笔记-wc命令

    命令参数: -c 统计字节数. -l 统计行数. -m 统计字符数.这个标志不能与 -c 标志一起使用. -w 统计字数.一个字被定义为由空白.跳格或换行字符分隔的字符串.

  3. ansible服务部署与使用

    第1章 ssh+key实现基于密钥连接(ansible使用前提) 说明:    ansible其功能实现基于SSH远程连接服务    使用ansible需要首先实现ssh密钥连接 1.1 部署ssh ...

  4. spacemacs 初始安装报错

    尝试使用emcas的配置文件spacemacs,第一次安装启动时,界面为纯白色,而且在输入完几个配置选项后,报了一个错误 Symbol's value as variable is void 根据官网 ...

  5. Lua 5.3 协程简单示例

    Lua 5.3 协程简单示例 来源 http://blog.csdn.net/vermilliontear/article/details/50547852 生产者->过滤器->消费者 模 ...

  6. windows下配置wampserver

    第一,打开局域网访问 配置文件:点击右下角的WAMP 服务器小托盘,选择Apache>httpd.conf 搜索关键字 "deny from ",会发现一处 "de ...

  7. Asp.Net 为什么需要异步

    之前看过别人提出为什么在本是多线程的Asp.Net下需要异步环境的时候,提出在Asp.Net环境下本身就是多线程,每个请求就是由一个专门IIS线程负责(咱不说Core下无IIS的情况).所以以此推论A ...

  8. CSS和文档

    1. 块级元素: p,div,ul,ol,h1,h2 . . . h6等.块级元素独占一行,旁边不能有其他元素. 2. 行内元素:span,a,strong,em等. display属性可以使块级元素 ...

  9. 万年历java

    public void showTime(){/*万年历 :  1900年1月20号是星期几?1月1号是星期一1月8号是星期一1月15号是星期一1%7 = 18%7 = 115%7 = 1★: 1. ...

  10. C#中泛型之Dictionary

    1.命名空间:System.Collections.Generic(程序集:mscorlib)2.描述: 1).从一组键(Key)到一组值(Value)的映射,每一个添加项都是由一个值及其相关连的键组 ...