Fetch API

161 阅读5分钟

Fetch API 概述

XMLHttpRequest的问题 1.所有的功能全部集中在同一个对象上,容易写出混乱不易维护的代码 2.采用传统的事件驱动方式,无法适配新的Promise API Fetch API的特点 1.并非取代AJAX,而是对AJAX传统API的改进 2.精细的功能分割:头部信息、请求信息、响应信息等均分不到不同的对象,更利于处理各种复杂的AJAX场景 3.使用Promis API,更利于异步代码的编写 4.Fetch API 并非ES6的内容,属于HTML5新增的Web API 5.需要掌握网络通信的知识

基本使用

使用fetch函数即可立即向服务器发送网络请求

参数

该函数有两个参数 1.必填,字符串,请求地址 2.选填,对象,请求配置 请求配置对象

  • method:字符串,请求方法,默认GET

  • headers:对象,请求头信息

  • body:请求体的内容,必须匹配请求头中的Content-Type

  • mode:字符串,请求模式

    • cors:默认值,配置为该值,会在请求头中加入origin和referer
    • no-cors:配置为该值,不会在请求头中加入origin和referer,跨域的时候可能出现问题
    • same-origin:指示请求必须在同一个域中发生,如果请求其他域,则报错
  • credentials:如何携带凭据(cookie)

    • omit:默认值,不携带cookie
    • same-origin:请求同源地址的时候,携带cookie
    • include:请求任何地址都携带cookie
  • cache:配置缓存模式

    • default:表示fetch请求之前检查一下http缓存

    • no-store:表示fetch请求将完全忽略http缓存的存在,这意味着请求之前将不再检查http的缓存,拿到响应后,他也不会更新http缓存

    • no-cache:如果存在缓存,那么fetch将发送一个条件查询requset和一个正常的request,拿到响应后,他会更新http缓存

    • reload:表示fetch请求之前将忽略http缓存的存在,但是拿到响应后,他主动更新http缓存

    • force-cache:表示fetch请求不顾一切的依赖缓存,即时缓存过期了,它依然从缓存中读取,除非没有任何缓存,那么它将发送一次正常的request

    • only-if-cached:表示fetch请求不顾一切的依赖缓存,即时缓存过期,他依然从缓存中读取,如果没有缓存,他将抛出网络错误(该设置只在mode为same-origin时有效)

返回值

fetch函数返回一个Promise对象

  • 当收到服务器的返回结果后,Promise进入resolve状态,状态数据为Response对象
  • 当网络发生错误(或者其他导致无法完成交互的错误)时,Promise进入rejected状态,状态数据为错误信息

Response对象

  • ok:boolen,当响应码在200-299之间为true,其他为false
  • status:number,响应的状态码
  • text():用于处理文本格式的Ajax响应。他从响应中获取文本流,将其读完,然后返回一个被解决为string对象的Promis
  • blob():用于处理二进制文件格式(比如图片或者电子表格)的Ajax响应。它读取文件的原始数据,一旦读取完整个我呢见,就返回一个被解决为blob对象的Promise
  • json():用于处理JSON格式的Ajax响应。他将JSON数据流转换为一个被解决为JavaScript对象的Promise
  • redirect():可用于重定向到另外一个URL。他会创建一个Promise,以解决来自重定向的URL的响应
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <button>获取数据</button>
  <script>
    async function getProvince() {
      const url = "http://example.com"
      const config = {
        method: 'GET'
      }
      const resp = await fetch(url, config)
      const result = await resp.json()
      console.log(result)
    }
    document.querySelector('button').onclick = function () {
      getProvince()
    }
  </script>
</body>

</html>

Request 对象

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

new Request(url地址, 配置)

注意点:

尽量保证每次请求都是一个新的Request对象

const request = new Request("https://www.mozilla.org/favicon.ico")
const url = request.url
const method = request.method;
const credentials  = request.credentials;
fetch(request)
    .then(resp => resp.blob())
	.then(blob => {
    image.src = URL.createObjectURL(blob)
})
const request = new Request("https://example.com", {
  method: "POST",
  body: '{"foo": "bar"}',
});
//备注: body 只能是一个 Blob、ArrayBuffer、TypedArray、DataView、FormData、URLSearchParams、ReadableStream 或 String 对象,也可以是一个字符串字面量,因此增加一个 JSON 对象的有效载荷则需要字符串化该对象。

Response对象

Response对象包含了很多属性和方法,也可以通过构造函数自定义该对象

const response = new Response()

Headers对象

Fetch API的Headers对象,允许你对HTTP请求头执行各种操作,包括检索、设置、添加、删除

使用Headers()构造方法创建一个新的Headers对象

const headers = new Heades({
    "Content-Type":"image/jpeg"
})

Headers实例有很多方法

  • append()方法可以追加一个新值到已经存在的headers上,或者新增加一个原本不存在的header

  • const headers = new Headers()
    headers.append("Content-Type","image/jpeg")
    headers.get("Content-Type") //"image/jpeg"
    headers.append("a","1")
    headers.append("a","2")
    headers.get("a") // 1,2
    
  • delete()方法可以从当前Headers对象中删除指定标头

  • const headers = new Headers()
    headers.append("Content-Type","image/jpeg")
    headers.delete("Content-Type")
    headers.get("Content-Type")//null
    
  • entries()方法以迭代器的形式返回Headers对象中所有键值对

  • const myHeaders = new Headers();
    myHeaders.append("Content-Type", "text/xml");
    myHeaders.append("Vary", "Accept-Language");
    for (var pair of myHeaders.entries()) {
      console.log(pair[0] + ": " + pair[1]);
    }
    //content-type: text/xml
    //vary: Accept-Language
    
  • has()方法判断当前Headers对象是否存在指定的标头

  • const myHeaders = new Headers();
    myHeaders.append("Content-Type", "text/xml");
    myHeaders.append("Vary", "Accept-Language");
    myHeaders.has("Content-Type") //true
    myHeaders.has("a") //false
    
  • keys()方法以迭代器的形式返回Headers对象中的所有key

  • const myHeaders = new Headers();
    myHeaders.append("Content-Type", "text/xml");
    myHeaders.append("Vary", "Accept-Language");
    for (var key of myHeaders.keys()) {
      console.log(key);
    }
    //Content-Type
    //Vary
    
  • set()方法可以在已经声明中的 Headers对象修改已有的一组键值对或者创建一个新的键值对,和append()方法不同的是,set对已经存在的key的值进行修改,append对已经存在的值是追加

  • var myHeaders = new Headers()
    myHeaders.append("Content-Type", "image/jpeg");
    myHeaders.set("Content-Type", "text/html");
    myHeaders.get("Content-Type") //text/html
    
  • values()方法以迭代器的形式返回Headers对象中的所有value

  • const myHeaders = new Headers();
    myHeaders.append("Content-Type", "text/xml");
    myHeaders.append("Vary", "Accept-Language");
    for (var value of myHeaders.values()) {
      console.log(value);
    }
    //text/xml
    //Accept-Language
    

文件上传

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <input type="file">
  <button>上传</button>
  <img src="" alt="" style="width: 100px; height: 100px;">
  <script>
    async function upload() {
      const input = document.querySelector("input")
      if (input.files.length === 0) {
        alert("请选择图片")
        return
      }
      const formData = new FormData(); //构建请求体
      formData.append("imagefile", input.files[0])
      const url = 'http://example/upload'
      const resp = await fetch(url, {
        method: "POST",
        body: formData////自动修改请求头
      })
      const result = await resp.json()
      return result
    }
    document.querySelector('button').onclick = async function () {
      const result = await upload();
      const img = document.querySelector('img');
      img.src = result.path
    }

  </script>
</body>

</html>