美文网首页
fetch详谈

fetch详谈

作者: 飘雪飞舞 | 来源:发表于2017-06-27 19:09 被阅读703次

    简介

    Fetch API 提供了一个 JavaScript接口,用于访问和操纵HTTP管道的部分,例如请求和响应。它还提供了一个全局 fetch()
    方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源。

    与ajax的区别

    1.从 fetch()返回的 Promise 将不会拒绝HTTP错误状态, 即使响应是一个 HTTP 404 或 500。相反,它会正常解决 (其中ok状态设置为false), 并且仅在网络故障时或任何阻止请求完成时,它才会拒绝。
    2.默认情况下, fetch在服务端不会发送或接收任何 cookies, 如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头)。
    说明:使用fetch模式,request header头是不会带cookies的,这样服务端就认为是不同的会话,解决方案:
    设置fetch的options就好,我的如下:
    const options= { method: "GET",mode: 'cors',credentials: 'include'};//same-origin
    我因为用cors,所以credentials设置为include,如果不跨域,那么same-origin就行了。

    特征检查

    可以通过检查 Headers、Request、Response 或 fetch 在 window 或 worker 作用域中是否存在,来检查是否支持 Fetch API。

    简单示例

    fetch API中最常用的是fetch方法,该方法最简单的形式是,接受一个 URL 参数并返回以一个 promise 对象:

    fetch("/data.json").then(function(res) {
      // res instanceof Response == true.
      if (res.ok) {
        res.json().then(function(data) {
          console.log(data.entries);
        });
      } else {
        console.log("Looks like the response wasn't perfect, got status", res.status);
      }
    }, function(e) {
      console.log("Fetch failed!", e);
    });
    

    如果提交的是一个post请求

    fetch("http://www.example.org/submit.php", {
      method: "POST",
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      body: "firstName=Nikhil&favColor=blue&password=easytoguess"
    }).then(function(res) {
      if (res.ok) {
        alert("Perfect! Your settings are saved.");
      } else if (res.status == 401) {
        alert("Oops! You are not authorized.");
      }
    }, function(e) {
      alert("Error submitting form!");
    });
    

    引入的接口

    Fetch 引入了 3 个接口,分别是 Headers,Request 和 Response。

    Headers

    Headers 接口是一个简单的键值对:

    var content = "Hello World";
    var reqHeaders = new Headers();
    reqHeaders.append("Content-Type", "text/plain"
    reqHeaders.append("Content-Length", content.length.toString());
    reqHeaders.append("X-Custom-Header", "ProcessThisImmediately");
    

    也可以给构造函数传一个多维数组或 JS 字面量对象:

    reqHeaders = new Headers({
      "Content-Type": "text/plain",
      "Content-Length": content.length.toString(),
      "X-Custom-Header": "ProcessThisImmediately",
    });
    

    结合fetch使用:

    var myHeaders = new Headers();
    
    var myInit = { method: 'GET',
                   headers: myHeaders,
                   mode: 'cors',
                   cache: 'default' };
    
    var myRequest = new Request('flowers.jpg', myInit);
    
    fetch(myRequest).then(function(response) {
      return response.blob();
    }).then(function(myBlob) {
      var objectURL = URL.createObjectURL(myBlob);
      myImage.src = objectURL;
    });
    

    Request

    通过构造一个 Request 对象来获取网络资源,构造函数需要 URL、method 和 headers 参数,同时也可以提供请求体(body)、请求模式(mode)、credentials 和 cache hints 等参数。

    var uploadReq = new Request("/uploadImage", {
      method: "POST",
      headers: {
        "Content-Type": "image/png",
      },
      body: "image data"
    });
    

    mode 参数用来决定是否允许跨域请求,以及哪些 response 属性可读。可选的 mode 值为 "same-origin"、"no-cors"(默认)以及 "cors"。

    same-origin

    该模式很简单,如果一个请求是跨域的,那么将返回一个 error,这样确保所有的请求遵守同源策略。

    no-cors

    该模式允许来自 CDN 的脚本、其他域的图片和其他一些跨域资源,但是首先有个前提条件,就是请求的 method 只能是HEAD
    、GET 或 POST。此外,如果 ServiceWorkers 拦截了这些请求,它不能随意添加或者修改除这些之外 Header 属性。第三,JS 不能访问 Response 对象中的任何属性,这确保了跨域时 ServiceWorkers 的安全和隐私信息泄漏问题。

    cors

    该模式通常用于跨域请求,用来从第三方提供的 API 获取数据。该模式遵守 CORS 协议,并只有有限的一些 Header 被暴露给 Response 对象,但是 body 是可读的。例如,获取一个 Flickr 最感兴趣的照片的清单:

    var u = new URLSearchParams();
    u.append('method', 'flickr.interestingness.getList');
    u.append('api_key', '<insert api key here>');
    u.append('format', 'json');
    u.append('nojsoncallback', '1');
     
    var apiCall = fetch('https://api.flickr.com/services/rest?' + u);
     
    apiCall.then(function(response) {
      return response.json().then(function(json) {
        // photo is a list of photos.
        return json.photos.photo;
      });
    }).then(function(photos) {
      photos.forEach(function(photo) {
        console.log(photo.title);
      });
    });
    

    另外,credentials 属性决定了是否可以跨域访问 cookie 。该属性与 XHR 的
    withCredentials 标志相同,但是只有三个值,分别是 omit(默认)、same-origin 和 include。

    Response

    Response 对象通常在 fetch() 的回调中获得,也可以通过 JS 构造,不过这通常只在 ServiceWorkers 中使用。

    处理 body

    在 Request 和 Response 对象中都可能有 body
    属性,并且 body
    可以是各种类型,比较复杂,所以前面我们故意先跳过它,在这里单独拿出来讲解。
    body
    可以是以下任何一种类型的实例:
    ArrayBuffer
    ArrayBufferView (Uint8Array and friends)
    Blob/File
    string
    URLSearchParams
    FormData —— 目前不被 Gecko 和 Blink 支持,Firefox 预计在版本 39 和 Fetch 的其他部分一起推出

    Fetch和promise不足

    1.不能中断,没有 abort、terminate、onTimeout 或 cancel 方法
    2.缺少其它一些方法:always,progress,finally
    3.没有 Deferred
    4.没有获取状态方法:isRejected,isResolved

    相关文章

      网友评论

          本文标题:fetch详谈

          本文链接:https://www.haomeiwen.com/subject/efvecxtx.html