HTML5 API fetch详解(如有细节纰漏, 欢迎指正)

Fetch API

回顾一下XMLHttpRequest的问题

  1. 所有的功能全部集中在一个对象上, 容易书写出混乱而且不容易维护的代码
  2. 采用传统的事件驱动模式, 无法适配新的 Promise api

Fetch Api的特点

  1. 并非取代ajax, 而是对ajax传统api的改进
  2. 精细的功能分割: 头部信息, 请求信息, 响应信息等均分布到不同的对象, 更利于处理各种复杂的ajax场景
  3. 使用Promise api, 更利于异步代码的书写
  4. fetch属于web api, 理所当然只能在浏览器端运行

Fetch Api的基本使用

参数

该函数有两个参数:

  1. 必填: 字符串, 对应的是请求地址
//请求数据的函数如下
const getDefaultData = () => {
    //在论坛中我找到了一个请求网易云音乐别人已经写好的接口,可以用来测试
    const url = 'https://api.imjad.cn/cloudmusic/?type=song&id=32785674'; 
    fetch(url); 
}

// 假设我们的html页面中有一个按钮, 点击这个按钮就会开始请求数据,然后我们现在获取到这个按钮
const btn = document.querySelector('button');
btn.onclick = () => {
    getDefaultData();
}

当上面的代码写好, 我们进行点击操作时, 服务器相应的给我们返回了数据
在这里插入图片描述

请求配置对象(红色为比较常用的, 绿色为目前不太常用的)

  • method: 字符串, 请求方法, 默认值GET
  • headers: 对象, 请求头信息
  • body: 请求体的内容, 必须匹配请求头中Content-Type
  • mode:字符串, 请求模式
    • cors: 默认值, 配置为该值, 会在请求头中加入origin和referer
    • no-cors: 配置为该值, 将不会再请求头中加入origin和referer, 跨域的时候可能会出现问题
    • same-origin: 配置为该值, 则指示请求必须在同一个域中发生, 如果请求其他域, 则会报错
  • credentials: 如何携带凭据
    • omit: 默认值, 不携带cookie
      - 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请求不顾一切的依赖缓存, 即使缓存过期了, 他依然从缓存中读取, 如果没有任何缓存, 那么他将抛出一个错误
//配置对象书写
const getData = function() {
    const url = 'xxx/api';
    const config = {
        method: 'POST',  // 写请求方法
        headers: {
            // 配置请求头
            //例如: "Content-Type": 'application/json'
        },
        body: {
            // 配置请求体, 比如POST请求要传递的数据
        }
        //...其他不常用配置
    }
    fetch(url, config); // 开始请求数据
}

返回值

fetch函数返回一个Promise对象

  • 当收到服务器的返回结果以后, Promise进入resolved状态, 状态数据为Response对象(服务器不一定要200返回, 只要返回了东西都会走resolved状态)
const getDefaultData = async () => {
            const url = 'https://api.imjad.cn/cloudmusic/?type=song&id=32785674';
            const config = {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: {

                },
                // mode: 'cors'
            }
            // 既然返回的结果是一个Promise, 那么我们就可以用await等待服务器响应的结果
            try {
                let promise = await fetch(url);
                console.log(promise);
            }catch(err) {
                console.log(err);
            }
        }
        const btn = document.querySelector('button');
        //当按钮点击的时候我们开始数据请求
        btn.onclick = function () {
            getDefaultData();
        }
  • 当网络发生错误(或者其他导致无法完成交互的错误), Promise进入rejected状态, 状态数据为错误信息

Response对象(服务器响应对象)

  1. ok: boolean, 当响应消息在200-299之间时为true, 其他为false
  2. status: number 响应的状态码
  3. text(): 用于处理文本格式的ajax响应, 他从响应中获取文本流, 将其读完, 然后返回一个被解决为string对象的Promise
const result = await fetch(url, config);
const respText = await result.text();
  1. blob(): 用于处理二进制的文件格式(比如图片和电子表格)的ajax响应, 他读取文件的原始数据, 一旦读取完整个文件, 就返回一个被解决为blob对象的Promise
const result = await fetch(url, config);
const respBlob = await result.blob(); 
  1. json(): 用于处理JSON格式的Ajax的响应, 他讲json数据流转化为一个被解决为JavaScript对象的Promise
const result = await fetch(url, config);
const respJson = await result.json(); 
  1. redirect(): 用于重定向到另一个url, 他会创建一个新的Promise, 以解决来自重定向的url响应
    响应对象示例
    在这里插入图片描述

来聊聊Request对象

除了使用基本的fetch方法, 还可以通过创建一个request对象来完成请求, 实际上fetch的内部也会帮你创建一个内部对象

//request对象的创建方式
new Request(url, config)

当我们遇到要复用某些请求的需求时, 就可以用到request对象

function getRespInfo() {
    const url = 'xxx/api';
    const config = {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
        },
    }
    //...body和其他配置
    const request = new Request(url, config);
}

}
function async getData() {
    // 每次都走一次getRespInfo这个函数, 保证每次创建的都是一个新的request对象
    const result = await fetch(getRespInfo());
    const respText = await result.text();
}

注意点: 尽量保证每次请求都是一个新的request对象

再来说说这个Response对象

大多数时候, Response对象都不需要我们自己来构建, 因为服务器会帮我们封装好, 但是在某些特殊时候, 比如后端数据还没写好, 在这种情况下,我们可能最先想到的就是mock数据, 但是我们也可以手动构建一个Response, 用来帮我们构建测试环境

// 我们有一个用来获取省市的函数
async function getProvince() {
    // 手动构建的Response对象
    const resp = new Response(
        `[
            {"id": 1, "name": "beijing"},
            {"id": 2, "name": "shanghai"}
        ]`,
        ok: true,
        status: 200
    )
    const result = await getJSON(resp);
    console.log(result);    
}

async function getJSON(resp) {
    return await resp.json();
}

但是因为我们大部分时间其实不会这样进行测试, 所以仅了解即可

[扩展] Headers对象

在Request和Response对象内部, 会将传递配置中的headers请求头对象转化为Headers对象

同时Headers对象提供一些方法:

  1. has(key): 判断请求头中是否存在指定的key
const url = 'xxx/api';
const config = {
    headers: {
        'Content-Type': 'application/json'
    }
}
const resp = new Request(url, config);
console.log(resp.headers.has('Content-Type')); //返回true, 因为我们请求头中配置了
  1. get(key): 得到请求头中对应的key所对应的值
const url = 'xxx/api';
const config = {
    headers: {
        'Content-Type': 'application/json'
    }
}
const resp = new Request(url, config);
console.log(resp.headers.get('Content-Type')); //返回'application/json'
  1. set(key, value): 修改请求头中对应的键值对, 如果是修改未存在的, 则会新建一个键值对
// 其余代码跟上面两个方法一样
resp.headers.set(c, 'helloworld'); //这时候请求头中会多出一个c 并且值为'helloworld'
  1. append(key, value): 专门用来往请求头中添加键值对
//其余代码跟上面三个方法一样
resp.headers.append(d, 'its tom'); //网请求头中添加一个d, 值为'its tom'

需要注意的是, 如果是对重复的属性用append,并不会覆盖之前的属性而是合并

// 假设headers中有a 值为1,然后我们调用append
resp.headers.append(a, 3); // 这时候headers中a的值为1,2 
  1. keys(): 得到所有的请求头的key所组成的集合(iterator)
const url = 'xxx/api';
const config = {
    headers: {
        'Content-Type': 'application/json',
        'a': 1
    }
}
const resp = new Request(url, config);
console.log(resp.headers.keys()); 
  1. values(): 得到所有的请求头key对应的值所组成的集合(iterator)
const url = 'xxx/api';
const config = {
    headers: {
        'Content-Type': 'application/json',
        'a': 1
    }
}
const resp = new Request(url, config);
console.log(resp.headers.values()); 
  1. entries(): 得到所有的请求头键值对所组成的集合(iterator)
const url = 'xxx/api';
const config = {
    headers: {
        'Content-Type': 'application/json',
        'a': 1
    }
}
const resp = new Request(url, config);
console.log(resp.headers.entries()); 

基础内容到此为止, 关于细节部分如果有问题 希望被指出, 好做更改, Thanks for reading

发布了33 篇原创文章 · 获赞 11 · 访问量 2270

猜你喜欢

转载自blog.csdn.net/weixin_44238796/article/details/103208659
今日推荐