fetch请求详解

灰太狼 2022-01-22 01:07 415阅读 0赞
最新更新时间:2019年06月04日16:18:30

《猛戳-查看我的博客地图-总有你意想不到的惊喜》

本文内容:fetch相关

概述

位于 WorkerOrGlobalScope 这一个 mixin 中的 fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。

Window 和 WorkerGlobalScope 都实现了 WorkerOrGlobalScope。 ——这意味着基本在任何场景下只要你想获取资源,都可以使用 位于 WorkerOrGlobalScope 中的 fetch() 方法。

Fetch API 提供了一个获取资源的接口(包括跨域请求),Fetch 是对 HTTP 接口的抽象,包括 Request,Response,Headers,Body。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。

Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。它同时还为有关联性的概念,例如CORS和HTTP原生头信息,提供一种新的定义,取代它们原来那种分离的定义。

fetch规范与jQuery.ajax()的两个不同点

当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。

默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。自从2017年8月25日后,默认的credentials政策变更为same-originFirefox也在61.0b13中改变默认值

兼容性方案

  1. if(window.fetch) {
  2. // run my fetch request here
  3. } else {
  4. // do something with XMLHttpRequest?
  5. }

语法

  1. //input 必填
  2. //[, init] 选填
  3. Promise<Response> fetch(input[, init]);

input 定义要获取的资源,可以是两种形式,如下简单请求的两种形式:url字符串 / Request对象

可选的配置项对象,包括所有对请求的设置。可选的参数有:
method, headers, body, mode, credentials, cache, redirect, referer, referrerPolicy, integerity

简单的请求

  1. //第一种形式
  2. let url = 'http://www.wanshaobo.com/1.jpg';//必传
  3. let options = {
  4. body: JSON.stringify(data),
  5. headers: new Headers({
  6. 'Content-Type': 'application/json',//发送数据方式为json
  7. //'Content-Type': 'application/x-www-form-urlencoded',//发送数据方式为表单提交
  8. }),
  9. method: 'POST',
  10. cache: "default",//default, reload, no-cache
  11. credentials: 'same-origin',//omit 不携带 same-origin 同源请求携带 include 无论跨域还是同源请求都会携带
  12. mode: 'cors'//cors, no-cors, same-origin, navigate
  13. };//可选
  14. fetch(url, options).then(function(Response){
  15. //fetch方法创建的Promise对象 返回resolved状态的回调函数
  16. //Response对象详解见下表
  17. },function(error){
  18. //fetch方法创建的Promise对象 返回rejected状态的回调函数
  19. })
  20. //第二种形式
  21. let Request = new Request(url, { method: 'POST', body: '{"foo":"bar"}'});
  22. fetch(Request).then(function(Response){
  23. //fetch方法创建的Promise对象 返回resolved状态的回调函数
  24. //Response对象详解见下表
  25. },function(error){
  26. //fetch方法创建的Promise对象 返回rejected状态的回调函数
  27. })
  • 属性




























































key value type
Response.headers 包含此Response所关联的Headers 对象 只读
Response.ok 包含了一个布尔值来标示该 Response 成功(状态码的范围在200-299) 只读
Response.redirected 表示该Response是否来自一个重定向,如果是的话,它的URL列表将会有多个entry 只读
Response.status 包含Response的状态码 只读
Response.statusText 包含了与该Response状态码一致的状态信息 (例如, OK对应 200) 只读
Response.type 包含Response的类型 (例如, basic, cors) 只读
Response.url 包含Response的URL 只读
Response.useFinalURL 包含了一个布尔值来标示这是否是该Response的最终URL -
Response.headers 包含此Response所关联的Headers 对象 只读
Response.headers 包含此Response所关联的Headers 对象 只读
  • 方法




















key value type
Response.json() 读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为JSON格式的promise对象。
Response.text() 读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为USVString格式的promise对象。

图片的请求demo

  1. //形式一
  2. var myImage = document.querySelector('img');
  3. var myRequest = new Request('flowers.jpg');
  4. fetch(myRequest).then(function(response) {
  5. return response.blob();
  6. }).then(function(response) {
  7. var objectURL = URL.createObjectURL(response);
  8. myImage.src = objectURL;
  9. });
  10. //形式二
  11. var myImage = document.querySelector('img');
  12. var myHeaders = new Headers();
  13. myHeaders.append('Content-Type', 'image/jpeg');
  14. var init = { method: 'GET', headers: myHeaders, mode: 'cors', cache: 'default' };
  15. var myRequest = new Request('flowers.jpg');
  16. fetch(myRequest,init).then(function(response) {
  17. ...
  18. });
  19. //形式三
  20. var myRequest = new Request('flowers.jpg',myInit);
  21. var init = {
  22. method: 'GET',
  23. headers: { 'Content-Type': 'image/jpeg' },
  24. mode: 'cors',
  25. cache: 'default'
  26. };
  27. var myRequest = new Request('flowers.jpg', init);
  28. fetch(myRequest).then(function(response) {
  29. ...
  30. });

完整的应用方案一

没有对fetch进行Promise包装,login方法的then回调是Response.json()返回的Promise实例
优点:代码简洁
缺点:不能在request方法体中做全局的res.code状态码统一处理,只能在login方法的then回调中做每一个请求的单独处理

  1. //实际的方法调用
  2. let requestData = { }
  3. login(requestData).then(res => {
  4. console.log('/abc 接口的返回值',res);// JSON from `response.json()` call
  5. }).catch(e => {
  6. console.log(e);
  7. })
  8. //业务的方法
  9. function login(obj) { //登录
  10. return request('/abc',obj)
  11. }
  12. //fetch的包装
  13. function request(url,data) {
  14. return fetch(baseURL + url, {
  15. body: JSON.stringify(data),
  16. headers: new Headers({ 'Content-Type': 'application/json'}),
  17. method: 'POST',
  18. cache: "default",
  19. credentials: 'include',//'same-origin' 'include'
  20. }).then(Response => Response.json(),err => { }).catch((e)=>{ })
  21. }

完整的应用方案二

对fetch进行Promise包装,在request方法体中做全局的res.code状态码统一处理,login方法的then回调是包装的Promise的返回值。

  1. //实际的方法调用
  2. let requestData = { }
  3. login(requestData).then(res => {
  4. //Promise对象resolved
  5. console.log('/abc 接口的返回值',res.data);
  6. },err => {
  7. //Promise对象rejecetd
  8. console.log(err)
  9. }).catch(e => {
  10. //catch方法处理 Promise 内部发生的错误,捕获两种错误:
  11. //1、then方法指定的两个回调函数,如果运行中抛出错误,会被catch方法捕获;
  12. //2、rejected状态也会被catch方法捕获
  13. //catch方法返回的还是一个 Promise 对象
  14. console.log(e);
  15. })
  16. //业务的方法
  17. function login(obj) { //登录
  18. return request('/abc',obj)
  19. }
  20. //fetch的包装
  21. import { message} from "antd";
  22. import { createBrowserHistory } from 'history';
  23. const history = createBrowserHistory();
  24. function request(url,data) {
  25. return new Promise((resolve,reject)=>{
  26. fetch(baseURL + url, {
  27. body: JSON.stringify(data),
  28. headers: new Headers({ 'Content-Type': 'application/json'}),
  29. method: 'POST',
  30. cache: "default",
  31. credentials: 'same-origin'
  32. }).then((Response)=>{
  33. //fetch请求返回resolved状态的回调函数
  34. let data = Response.json()//res是一个json文件,使用 json() 读取并解析数据,返回一个被解析为JSON格式的promise对象
  35. data.then((res,rej)=>{
  36. if(res.code == 100){
  37. resolve(res)
  38. }else if(res.code == 11115){
  39. //用户登录失效,token失效,跳转到登录页面
  40. history.replace('/login')
  41. }else{
  42. message.destroy()
  43. message.error(res.message);
  44. }
  45. })
  46. },err => {
  47. //fetch请求返回rejected状态的回调函数
  48. //fetch请求 网络故障时或请求被阻止时,标记为 reject
  49. reject(err)
  50. }).catch((e)=>{
  51. reject(e)
  52. })
  53. })
  54. }

完整的应用方案三:FormData() 和fetch()上传文件

body使用FromData对象,主要用于序列化表单以及创建与表单格式相同的数据
通过HTML元素,FormData() 和fetch()上传文件。

  1. var formData = new FormData();
  2. var fileField = document.querySelector("input[type='file']");
  3. formData.append('username', 'abc123');
  4. formData.append('avatar', fileField.files[0]);
  5. function request(url,data) {
  6. return new Promise((resolve,reject)=>{
  7. fetch(url, {
  8. body: formData,
  9. method: 'PUT',
  10. }).then((Response)=>{
  11. let data = Response.json()
  12. data.then((res,rej)=>{
  13. })
  14. })
  15. })
  16. }

完整的应用方案四:FormData() 和fetch()上传多个文件

可以通过HTML元素,FormData() 和fetch()上传文件。

  1. var formData = new FormData();
  2. var photos = document.querySelector("input[type='file'][multiple]");
  3. formData.append('title', 'My Vegas Vacation');
  4. formData.append('photos', photos.files);
  5. function request(url,data) {
  6. return new Promise((resolve,reject)=>{
  7. fetch(url, {
  8. body: formData,
  9. method: 'PUT',
  10. }).then((Response)=>{
  11. let data = Response.json()
  12. data.then((res,rej)=>{
  13. })
  14. })
  15. })
  16. }

参考资料

  • Fetch API - Web API
  • 使用 Fetch - Web API
  • WorkerOrGlobalScope.fetch() - Web API
  • Request - Web API
  • Response - Web API
  • Headers - Web API
  • Body - Web API

感谢阅读,欢迎评论^-^

打赏我吧^-^

发表评论

表情:
评论列表 (有 0 条评论,415人围观)

还没有评论,来说两句吧...

相关阅读

    相关 fetch请求详解

    最新更新时间:2019年06月04日16:18:30 [`《猛戳-查看我的博客地图-总有你意想不到的惊喜》`][-_-] > 本文内容:fetch相关 概述