设为首页 加入收藏

TOP

全面分析前端的网络请求方式(四)
2019-09-17 19:09:38 】 浏览:136
Tags:全面 分析 前端 网络 请求 方式
浏览器完全支持,所以你仍然需要一个polyfill

八、fetch 的使用

一个基本的 fetch 请求:

const options = {
    method: "POST", // 请求参数
    headers: { "Content-Type": "application/json" }, // 设置请求头
    body: JSON.stringify({ name: "123" }), // 请求参数
    credentials: "same-origin", // cookie设置
    mode: "cors" // 跨域
};
fetch("http://www.xxx.com")
    .then(function(response) {
        return response.json();
    })
    .then(function(myJson) {
        console.log(myJson); // 响应数据
    })
    .catch(function(err) {
        console.log(err); // 异常处理
    });

Fetch API提供了一个全局的fetch()方法,以及几个辅助对象来发起一个网络请求。

  • fetch()

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

  • Headers

可以通过Headers()构造函数来创建一个你自己的headers对象,相当于 response/request 的头信息,可以使你查询到这些头信息,或者针对不同的结果做不同的操作。

var myHeaders = new Headers();
myHeaders.append("Content-Type", "text/plain");
  • Request

通过Request()构造函数可以创建一个Request对象,这个对象可以作为fetch函数的第二个参数。

  • Response

fetch()处理完promises之后返回一个Response实例,也可以手动创建一个Response实例。

九、fetch polyfill 源码分析

由于fetch是一个非常底层的API,所以我们无法进一步的探究它的底层,但是我们可以借助它的polyfill探究它的基本原理,并找出其中的坑点。

代码结构

由代码可见,polyfill主要对Fetch API 提供的四大对象进行了封装:

fetch 封装

代码非常清晰:

  • 构造一个Promise对象并返回
  • 创建一个Request对象
  • 创建一个XMLHttpRequest对象
  • 取出Request对象中的请求url,请求方发,open一个xhr请求,并将Request对象中存储的headers取出赋给 xhr
  • xhr onload后取出responsestatusheadersbody封装Response对象,调用resolve

异常处理

可以发现,调用reject有三种可能:

  • 1.请求超时
  • 2.请求失败

注意:当和服务器建立简介,并收到服务器的异常状态码如404、500等并不能触发onerror。当网络故障时或请求被阻止时,才会标记为 reject,如跨域、url不存在,网络异常等会触发onerror

所以使用 fetch 当接收到异常状态码都是会进入 then 而不是 catch。这些错误请求往往要手动处理。

  • 3.手动终止

可以在request参数中传入signal对象,并对signal对象添加abort事件监听,当xhr.readyState变为4(响应内容解析完成)后将 signal 对象的 abort 事件监听移除掉。

这表示,在一个fetch请求结束之前可以调用signal.abort将其终止。在浏览器中可以使用AbortController()构造函数创建一个控制器,然后使用AbortController.signal属性

这是一个实验中的功能,此功能某些浏览器尚在开发中

Headers 封装

在 header 对象中维护了一个map对象,构造函数中可以传入Header对象、数组、普通对象类型的header,并将所有的值维护到map中。

之前在fetch函数中看到调用了headerforEach方法,下面是它的实现:

可见header的遍历即其内部map的遍历。

另外Header还提供了append、delete、get、set等方法,都是对其内部的map对象进行操作。

Request 对象

2019-05-30-wlqq_10

Request对象接收的两个参数即fetch函数接收的两个参数,第一个参数可以直接传递url,也可以传递一个构造好的request对象。第二个参数即控制不同配置的option对象。

可以传入credentials、headers、method、mode、signal、referrer等属性。

这里注意:

  • 传入的headers被当作Headers构造函数的参数来构造 header 对象。

fetch 函数中还有如下的代码:

if (request.credentials === "include") {
    xhr.withCredentials = true;
} else if (request.credentials === "omit") {
    xhr.withCredentials = false;
}

默认的credentials类型为same-origin,即可携带同源请求的 coodkie。

然后我发现这里 polyfill 的实现和MDN-使用 Fetch以及很多资料是不一致的:

mdn: 默认情况下,fetch 不会从服务端发送或接收任何 cookies

于是我分别实验了下使用polyfill和使用原生fetch携带 cookie 的情况,发现在不设置credentials的情况下居然都是默认携带同源cookie的,这和文档的说明说不一致的,查阅了许多资料后都是说fetch默认不会携带 cookie,下面是使用原生fetch在浏览器进行请求的情况:

2019-05-30-wlqq_11

然后我发现在已经指出新版浏览器credentials默认值已更改为same-origin,旧版依然是omit

确实MDN-使用 Fetch这里的文档更新的有些不及时,误人子弟了…

Response 对象

Response对象是fetch调用成功后的返回值:

回顾下fetch中对Response`的操作:

xhr.onload = function() {
    var options = {
        status: xhr.status,
        statusText: xhr.statusText,
        headers: parseHeaders(xhr.getAllResponseHeaders() || "")
    };
    options.url =
        "responseURL" in xhr
            ? xhr.responseURL
            : options.headers.get("X-Request-URL");
    var bo
首页 上一页 1 2 3 4 5 6 下一页 尾页 4/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇JS异步解决方案 下一篇js闭包函数

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目