找回密码
 立即注册
查看: 31685|回复: 99

大前端的未来可能代替ajax的东西——Fetch API初体验

    [复制链接]
  • TA的每日心情
    郁闷
    2022-12-4 03:02
  • 签到天数: 495 天

    连续签到: 2 天

    [LV.9]妙领天机

    727

    主题

    3017

    回帖

    5216

    积分

    VIP会员

    积分
    5216
    发表于 2018-7-23 20:38:16 | 显示全部楼层 |阅读模式

    马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

    您需要 登录 才可以下载或查看,没有账号?立即注册

    ×

      JavaScript通过XMLHttpRequest(XHR)来执行异步请求,这个方式从web发展之初至今已经存在了很长一段时间。虽说它很有用,但它不是最佳API。它在设计上不符合职责分离原则,将输入、输出和用事件来跟踪的状态混杂在一个对象里。而且,基于事件的模型与最近JavaScript流行的Promise以及基于生成器的异步编程模型不太搭(事件模型在处理异步上有点过时了)。
      新的 Fetch API打算修正上面提到的那些缺陷。
      它向JS中引入和HTTP协议中同样的原语(即Fetch)。具体而言,它引入一个实用的函数fetch()用来简洁捕捉从网络上检索一个资源的意图。
      Fetch 规范的API明确了用户代理获取资源的语义。它结合ServiceWorkers,尝试达到以下优化:
      改善离线体验
      保持可扩展性
      到写这篇文章的时候,Fetch API被Firefox 39(Nightly版)以及Chrome 42(开发版)支持。在github上,有基于低版本浏览器的兼容实现
      特性检测
      要检查是否支持Fetch API,可以通过检查 Headers, Request, Response 或者 fetch 在 window 或者 worker 作用域中是否存在。
      简单的fetching示例
      在Fetch API中,最常用的就是fetch()函数。它接收一个URL参数,返回一个promise来处理response。response参数带着一个Response对象。

                                   
    登录/注册后可看大图

      如果是提交一个POST请求,代码如下:

                                   
    登录/注册后可看大图

      fetch()函数的参数和传给Request()构造函数的参数保持完全一致,所以你可以直接传任意复杂的request请求给fetch()。
      Headers
      Fetch引入了3个接口,它们分别是 Headers,Request 以及 Response 。他们直接对应了相应的HTTP概念,但是基于安全考虑,有些区别,例如支持CORS规则以及保证cookies不能被第三方获取。
      Headers接口是一个简单的多映射的名-值表

                                   
    登录/注册后可看大图

      也可以传一个多维数组或者json:

                                   
    登录/注册后可看大图

      Headers的内容可以被检索:

                                   
    登录/注册后可看大图

      一些操作不仅仅对ServiceWorkers有用,本身也提供了更方便的操作Headers的API(相对于XMLHttpRequest来说)。
      由于Headers可以在request请求中被发送或者在response请求中被接收,并且规定了哪些参数是可写的,Headers对象有一个特殊的guard属性。这个属性没有暴露给Web,但是它影响到哪些内容可以在Headers对象中被改变。
      可能的值如下:
      “none”: 默认的
      “request”: 从Request中获得的Headers只读。
      “request-no-cors”:从不同域的Request中获得的Headers只读。
      “response”: 从Response获得的Headers只读。
      “immutable” 在ServiceWorkers中最常用的,所有的Headers都只读。
      哪一种 guard 作用于 Headers 导致什么行为,详细定义在了这个规范中。例如,你不可以添加或者修改一个guard属性是”request”的Request Headers的”Content-Length”属性。同样地,插入”Set-Cookie”属性到一个Response headers是不允许的,因此ServiceWorkers是不能给合成的Response的headers添加一些cookies。
      如果使用了一个不合法的HTTP Header属性名,那么Headers的方法通常都抛出 TypeError 异常。如果不小心写入了一个不可写的属性,也会抛出一个 TypeError 异常。除此以外的情况,失败了并不抛出异常。例如:

                                   
    登录/注册后可看大图

      Request
      Request接口定义了通过HTTP请求资源的request格式。参数需要URL、method和headers,同时Request也接受一个特定的body,mode,credentials以及cache hints.
      最简单的 Request 当然是一个URL,可以通过URL来GET一个资源。

                                   
    登录/注册后可看大图

      你也可以将一个建好的Request对象传给构造函数,这样将复制出一个新的Request。

                                   
    登录/注册后可看大图

      这种用法通常见于ServiceWorkers。
      URL以外的其他属性的初始值能够通过第二个参数传给Request构造函数。这个参数是一个json:

                                   
    登录/注册后可看大图

      mode属性用来决定是否允许跨域请求,以及哪些response属性可读。可选的mode属性值为same-origin,no-cors(默认)以及cors。
      same-origin模式很简单,如果一个请求是跨域的,那么返回一个简单的error,这样确保所有的请求遵守同源策略。

                                   
    登录/注册后可看大图

      no-cors模式允许来自CDN的脚本、其他域的图片和其他一些跨域资源,但是首先有个前提条件,就是请求的method只能是”HEAD”,”GET”或者”POST”。此外,任何 ServiceWorkers 拦截了这些请求,它不能随意添加或者改写任何headers,除了这些。第三,JavaScript不能访问Response中的任何属性,这保证了 ServiceWorkers 不会导致任何跨域下的安全问题而隐私信息泄漏。
      cors模式我们通常用作跨域请求来从第三方提供的API获取数据。这个模式遵守CORS协议。只有有限的一些headers被暴露给Response对象,但是body是可读的。例如,你可以获得一个Flickr的最感兴趣的照片的清单:

                                   
    登录/注册后可看大图


                                   
    登录/注册后可看大图

      你无法从Headers中读取”Date”属性,因为Flickr在Access-Control-Expose-Headers中设置了不允许读取它。

                                   
    登录/注册后可看大图

      credentials枚举属性决定了cookies是否能跨域得到。这个属性与XHR的withCredentials标志相同,但是只有三个值,分别是”omit”(默认),”same-origin”以及”include”。
      Request对象也可以提供 caching hints 给用户代理。这个属性还在安全复审阶段。Firefox 提供了这个属性,但是它目前还不起作用。
      Request还有两个只读的属性与ServiceWorks拦截有关。其中一个是referrer,表示Request的来源,可能为空。另外一个是context,是一个非常大的枚举集合定义了获得的资源的种类,它可能是image比如请求来自于img标签,可能是worker如果是一个worker脚本,等等。如果使用fetch()函数,这个值是fetch。
      Response
      Response实例通常在fetch()的回调中获得。但是它们也可以用JS构造,不过通常这招只用于ServiceWorkers。
      Response中最常见的成员是status(一个整数默认值是200)和statusText(默认值是”OK”),对应HTTP请求的status和reason。还有一个”ok”属性,当status为2xx的时候它是true。
      headers 属性是Response的Headers对象,它是只读的(with guard “response”),url属性是当前Response的来源URL。
      Response 也有一个type属性,它的值可能是”basic”,”cors”,”default”,”error”或者”opaque。
      “basic”: 正常的,同域的请求,包含所有的headers除开”Set-Cookie”和”Set-Cookie2″。
      “cors”: Response从一个合法的跨域请求获得,一部分header和body可读。
      “error”: 网络错误。Response的status是0,Headers是空的并且不可写。当Response是从Response.error()中得到时,就是这种类型。
      “opaque”: Response从”no-cors”请求了跨域资源。依靠Server端来做限制。
      “error”类型会导致fetch()函数的Promise被reject并回调出一个TypeError。
      还有一些属性只在ServerWorker作用域下有效。以正确的方式 返回一个Response针对一个被ServiceWorkers拦截的Request,可以像下面这样写:

                                   
    登录/注册后可看大图

      如你所见,Response有个接收两个可选参数的构造器。第一个参数是返回的body,第二个参数是一个json,设置status、statusText以及headers。
      静态方法Response.error()简单返回一个错误的请求。类似的,Response.redirect(url, status)返回一个跳转URL的请求。
      处理body
      无论Request还是Response都可能带着body。由于body可以是各种类型,比较复杂,所以前面我们故意先略过它,在这里单独拿出来讲解。
      body可以是以下任何一种类型的实例:
      ArrayBuffer
      ArrayBufferView(Uint8Array and friends)
      Blob/File
      字符串
      URLSearchParams
      FormData——目前不被Gecko和Blink支持,Firefox预计在版本39和Fetch的其他部分一起推出。
      此外,Request和Response都为他们的body提供了以下方法,这些方法都返回一个Promise对象。
      arrayBuffer()
      blob()
      json()
      text()
      formData()
      在使用非文本的数据方面,Fetch API和XHR相比提供了极大的便利。
      可以通过传body参数来设置Request的body:

                                   
    登录/注册后可看大图

      Response的第一个参数是body:

                                   
    登录/注册后可看大图

      Request和Response(通过fetch()方法)都能够自动识别自己的content type,Request还可以自动设置”Content-Type” header,如果开发者没有设置它的话。
      留和克隆
      非常重要的一点要说明,那就是Request和Response的body只能被读取一次!它们有一个属性叫bodyUsed,读取一次之后设置为true,就不能再读取了。

                                   
    登录/注册后可看大图

      这样设计的目的是为了之后兼容基于流的API,让应用一次消费data,这样就允许了JavaScript处理大文件例如视频,并且可以支持实时压缩和编辑。
      有时候,我们希望多次访问body,例如,你可能想用即将支持的Cache API去缓存Request和Response,以便于可以离线使用,Cache要求body能被再次读取。
      所以,我们该如何让body能经得起多次读取呢?API提供了一个clone()方法。调用这个方法可以得到一个克隆对象。不过要记得,clone()必须要在读取之前调用,也就是先clone()再读取。
      未来的改进
      为了支持流,Fetch最终将提供可以中断执行读取资源的能力,并且提供可以得到读取进度的API。这些能力在XHR中有,但是想要实现成Promise-based的Fetch API有些麻烦。
    楼主热帖
  • TA的每日心情
    无聊
    2019-8-30 04:20
  • 签到天数: 466 天

    连续签到: 6 天

    [LV.9]妙领天机

    0

    主题

    3165

    回帖

    3161

    积分

    声名显赫

    积分
    3161
    发表于 2018-7-23 20:53:08 | 显示全部楼层
    鼎力支持!!
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2019-8-30 09:06
  • 签到天数: 474 天

    连续签到: 3 天

    [LV.9]妙领天机

    3

    主题

    3066

    回帖

    3064

    积分

    声名显赫

    积分
    3064
    发表于 2018-7-24 20:35:20 | 显示全部楼层
    支持,赞一个
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2019-8-30 08:13
  • 签到天数: 469 天

    连续签到: 3 天

    [LV.9]妙领天机

    12

    主题

    3046

    回帖

    3068

    积分

    声名显赫

    积分
    3068
    发表于 2018-7-25 11:12:21 | 显示全部楼层
    众里寻他千百度,蓦然回首在这里!
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2019-8-30 02:20
  • 签到天数: 468 天

    连续签到: 1 天

    [LV.9]妙领天机

    1

    主题

    3073

    回帖

    3076

    积分

    声名显赫

    积分
    3076
    发表于 2018-7-26 07:50:21 | 显示全部楼层
    我也来顶一下..
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2019-8-30 10:21
  • 签到天数: 473 天

    连续签到: 1 天

    [LV.9]妙领天机

    4

    主题

    3050

    回帖

    3052

    积分

    声名显赫

    积分
    3052
    发表于 2018-7-26 10:11:40 | 显示全部楼层
    确实不错,顶先
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2021-9-14 11:28
  • 签到天数: 483 天

    连续签到: 1 天

    [LV.9]妙领天机

    449

    主题

    3048

    回帖

    4379

    积分

    如雷贯耳

    积分
    4379
    发表于 2018-7-26 20:12:49 | 显示全部楼层
    支持,赞一个
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2019-8-30 15:02
  • 签到天数: 469 天

    连续签到: 3 天

    [LV.9]妙领天机

    5

    主题

    3086

    回帖

    3094

    积分

    声名显赫

    积分
    3094
    发表于 2018-7-27 16:09:26 | 显示全部楼层
    无论是不是沙发都得回复下
    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2019-8-30 02:28
  • 签到天数: 475 天

    连续签到: 2 天

    [LV.9]妙领天机

    8

    主题

    3098

    回帖

    3113

    积分

    声名显赫

    积分
    3113
    发表于 2018-8-1 06:37:45 | 显示全部楼层
    众里寻他千百度,蓦然回首在这里!
    回复

    使用道具 举报

  • TA的每日心情
    郁闷
    2019-8-29 13:51
  • 签到天数: 468 天

    连续签到: 2 天

    [LV.9]妙领天机

    4

    主题

    3017

    回帖

    3023

    积分

    声名显赫

    积分
    3023
    发表于 2018-8-1 16:13:52 | 显示全部楼层
    好,很好,非常好!
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|手机版|小黑屋|任逍遥

    GMT+8, 2024-11-22 20:45 , Processed in 0.123143 second(s), 49 queries .

    Powered by 任逍遥 X3.5

    Copyright © 2001-2024, Rxiaoyao Cloud.

    快速回复 返回顶部 返回列表