资讯专栏INFORMATION COLUMN

异步请求与Fetch

vibiu / 3010人阅读

摘要:再谈异步请求语言将任务的执行模式分成两种同步和异步。通过对象及时监听完成事件,执行事件回调函数不会堵塞程序运行。新的是异步请求的另一种方案,比起其复杂糅杂的写法,能更简洁的获取到数据。提供了对和以及其他与网络请求有关的对象的通用定义。

再谈异步请求

Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

在浏览器,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。通过XHRHttpRequest对象及时监听完成事件,执行事件回调函数不会堵塞程序运行。

关于Fetch

Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应。它还提供了一个全局 fetch()方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源。这种功能以前是使用 XMLHttpRequest实现的。Fetch提供了一个更好的替代方法,可以很容易地被其他技术使用,例如 Service Workers。Fetch还提供了单个逻辑位置来定义其他HTTP相关概念,例如 CORS和HTTP的扩展。

新的Fetch API是XHRHttpRequest异步请求的另一种方案,比起其复杂糅杂的写法,fetch能更简洁的获取到数据。

XHRHttpRequest使用事件回调函数容易进入回调地狱,而Fetch Api接收url参数返回Promise对象。

Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。使之今后可以被使用到更多地应用场景中

Fetch的简单使用
let url = "http://jsonplaceholder.typicode.com/users"
fetch(url).then((res)=>{
  console.log(res)
}).catch((err)=>{})

将url传递给fetch时会立即返回一个promise对象此时的状态是pending,当promise被通过时会返回一个response对象。如果我们用习惯了比如jquery封装好的ajax方法,很容易会以为上面的res就是返回的data。

fetch 只有在遇到网络错误的时候才会 reject 这个 promise,比如用户断网或请求地址的域名无法解析等。只要服务器能够返回 HTTP 响应(甚至只是 CORS preflight 的 OPTIONS 响应),promise 一定是 resolved 的状态。

fetch返回Promise对象

Response简介

response.type有以下几种

basic 标准值,同源响应

cors 收到一个有效的跨域请求

opaque 跨域请求但服务器没有返回cors响应头

但是无效的跨域请求如果像下面这么写,其实根本无法拿到response对象

request.mode用于确定跨域请求是否导致有效的响应

same-origin 同源情况下才可请求成功,否则抛出错误

比如在有效的跨域请求设置这个模式会提示
Fetch API cannot load http://jsonplaceholder.typico... Request mode is "same-origin" but the URL"s origin is not same as the request origin file://.

cors: 表示同域和带有CORS响应头的跨域下可请求成功.

cors-with-forced-preflight: 表示在发出请求前, 将执行preflight检查.

no-cors: 用于跨域相应不带cors的情况,此时相应类型为opaque

根据上面的错误修改fetch的模式就可以返回response对象了,可以对比发现无效跨域请求并没有返回什么有价值的信息例如url,status,statusText等

reponse.body属于ReadableStream类型

当读取CSV等大文件时通过流来读取,可以选择在读取到要获取的数据后停止流,而不是获取到全部响应数据再去查找。

对于常用返回的几种数据类型,可以使用blob()、text()、formData()、json(),这几种方法都会讲body标记为已读数据,所以想再次获取的时候就会报错

比如下面的代码,真实返回的数据不是json类型的,想利用catch方法去捕获然后再次返回text类型,浏览器时会报TypeError: Already read

fetch(url).then(function(response) {
  return response.json().catch(function() {
    return response.text();
  });
});

正确的方式是使用clone()方法先对数据进行拷贝,响应数据通过clone并不会被回收,一直留在内存中,直至被读取

fetch(url).then(function(response) {
  return response.clone().json().catch(function() {
    return response.text();
  });
});

Request简介

method:设置请求方法,默认GET方法

credentials fetch方法默认不发送cookies,如果遇到401 Unauthorized没有权限问题就要看看是否有设置credentials

omit: 从不发送cookies.

same-origin: 只有当URL与响应脚本同源才发送cookies.

include: 总是发送cookies, 即使来自跨域的请求

默认情况下请求不带coookie

cache 设置缓存,跟XHR对比在请求时就可以控制缓存,虽然这是有争议的,因为这暴露了用户历史记录

default

如果是最新的资源,则返回缓存

如果资源已过期则向服务器发出条件请求;如果服务器指示资源没有改变则返回缓存;否则从服务器中下载,并更新缓存。

如果没有找到缓存则发出正常情求,但不缓存资源。

no-store 直接从服务器获取资源并且不会将资源缓存

reload 直接从服务器获取资源,并且缓存资源

no-cache

如果资源有效或者过期,浏览器会发出一个条件请求,如果服务器返回没有改变,则返回缓存,否则,重新获取资源并更新缓存

如果不存在资源则浏览器发出正常请求下载并更新缓存

force-cache

如果有缓存直接返回缓存,否则下载更新资源

only-if-cached

如果有缓存直接返回缓存,否则浏览器返回错误

XHR和Fetch其他的对比

fetch没有xhr中的abort()方法来中断请求

fetch没有progress进度事件监听数据,但是你可以通过获取content-length计算进度

XHR open方法有最后一个参数设为false的时候是同步请求,fetch没有提供同步请求的方法,但同步请求并不常用

fetch 并没有像XHR的timeout属性来设置延时

Fetch实践体验

习惯了像是vue-resource等插件封装好的get,post方法,在使用fetch的时候很容易会被它看似简洁的api给迷惑

fetch兼容性问题

我们需要引入fetch 的polyfill,扒开源码我们可以发现实现原理还是建立在XMLHttpRequest上的,但是由于polyfill要实现fetch如Blob类文件对象等,在safari和ie上还是有兼容性问题的

参数传递问题

在get请求方式中,我们还是只能像xhr那样以拼接url字符串的方式来传递,这与fetch看起来简洁的api有点不符。

虽然原生的URLSearchParams 接口定义了用来处理 URL 参数串的方法。但是这个api目前兼容性也是不怎么好

var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"

在post请求中,数据要以body字段来传递参数,也就是说我们要常用的json格式要经过下面格式的转换,就像XMLHttpRequest那样

body 可以是以下任何一种类型的实例:

ArrayBuffer
ArrayBufferView (Uint8Array and friends)
Blob/File
string
URLSearchParams
FormData

响应数据的问题

在回调函数中我们首先接受到的是response对象,由于body是ReadableStream类型,几乎很难预先判断数据是什么类型,也就很难判断是到底用text()、json()方法解析数据

response对象有一个bodyUsed的属性初始是false,调用text()、json()等方法会读取Response对象并且将它设置为已读,这时bodyUsed为true

bodyUsed初始值为false

- 解决办法有两种但都有一定的不足
     1.是通过clone加catch方式找到正确的输出方式,但是要注意调用方法的顺序,不然一个json有可能最后还是以text的方式解析,还要注意的是最后要将response的数据回收或者读取,因为clone方法的读取并不影响原来的reponse对象
fetch(url).then(function(response) {
      return response.json().catch(function() {
         return response.text();
      });
});
  2.是通过判断content-type的方式,如果已知的返回格式不多的情况下用还是不错的选择
fetch(url).then(function(response) {
      if (response.headers.get("Content-Type") === "application/json") {
        return response.json();
      }
      return response.text();
});
小结

基于promise的fecth方法可以让我们远离回调地狱而不需要其他的封装。

fetch 将 response.body 设计成 ReadableStream 其实是非常有前瞻性的,这种设计让你在请求大体积文件时变得非常有用。

参考资料:https://jakearchibald.com/201...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/83899.html

相关文章

  • 对python并发编程的思考

    摘要:我们以请求网络服务为例,来实际测试一下加入多线程之后的效果。所以,执行密集型操作时,多线程是有用的,对于密集型操作,则每次只能使用一个线程。说到这里,对于密集型,可以使用多线程或者多进程来提高效率。 为了提高系统密集型运算的效率,我们常常会使用到多个进程或者是多个线程,python中的Threading包实现了线程,multiprocessing 包则实现了多进程。而在3.2版本的py...

    sshe 评论0 收藏0
  • ES6 Fetch API HTTP请求实用指南

    摘要:例子张三删除用户为了删除用户,我们首先需要定位用户,然后我们定义方法类型。例子张三结论现在,你已基本了解如何使用的从服务器检索或操作资源,以及如何处理。您可以使用本文作为如何构建操作的请求的指南。 showImg(https://segmentfault.com/img/bVbjxqh?w=1000&h=562); 本次将介绍如何使用Fetch API(ES6 +)对REST API的...

    Sunxb 评论0 收藏0
  • JavaScript 异步进化史

    摘要:签订协议的两方分别是异步接口和。在异步函数中,使用异常捕获的方案,代替了的异常捕获的方案。需要注意的是,在异步函数中使异步函数用时要使用,不然异步函会被同步执行。 同步与异步 通常,代码是由上往下依次执行的。如果有多个任务,就必需排队,前一个任务完成,后一个任务才会执行。这种执行模式称之为: 同步(synchronous) 。新手容易把计算机用语中的同步,和日常用语中的同步弄混淆。如,...

    luzhuqun 评论0 收藏0
  • tornado6python3.7 异步新姿势

    摘要:这是我重新复习的原因放弃了之前自己实现的全面拥抱的这个改动是非常大的而且阅读的源码可以发现其中大部分函数都支持了类型检验和返回值提示值得阅读 废话不多说,直接上代码 __auth__ = aleimu __doc__ = 学习tornado6.0+ 版本与python3.7+ import time import asyncio import tornado.gen import t...

    maxmin 评论0 收藏0
  • Fluent Fetcher: 重构基于 Fetch 的 JavaScript 网络请求库

    摘要:重构基于的网络请求库从属于笔者的开发基础与工程实践系列文章与项目,记述了笔者对内部使用的封装库的设计重构与实现过程。基本使用版本中的中,最核心的设计变化在于将请求构建与请求执行剥离了开来。而函数则负责执行请求,并且返回经过扩展的对象。 Fluent Fetcher: 重构基于 Fetch 的 JavaScript 网络请求库从属于笔者的 Web 开发基础与工程实践系列文章与项目,记述了...

    Yangder 评论0 收藏0

发表评论

0条评论

vibiu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<