zoukankan      html  css  js  c++  java
  • JavaScript中的Fetch函数

    JavaScript中的Fetch函数

    Fetch API提供了一个JavaScript接口,用于访问和操作Http管道的一些具体的部分,例如请求和响应。还提供一个fetch()方法,该方法提供一种简单,合理的方式来跨网络异步获取资源。

    这种功能以前是使用XMLHttpRequest实现的。Fetch挺了一个更理想的替代方案,可以很容易的被其他技术使用。例如Service Workers。Fetch还提供了专门的逻辑空间来定义其他与Http相关的概念,例如Cors和http扩展。

    注意:fetch规范与Jquery.ajax()主要有三种方式不同:

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

    2.fetch()不会接受跨域的cookies,也不能使用fetch建立跨域会话,其他网站的set-cookies头部字段将会被无视。

    年tch不会发送cookies,除非使用了credentials的初始化选项。2017年8月25日后,默认的credentials政策更改为same-origin。fixfox在61.0b134版本进行了修改。

    示例:

    fetch(url)
    .then(function(response){return response.json()})
    .then(function(myJson){console.log(myJson)})

    示例中通过网络获取一个json文件并将其打印到控制台。

    最简单的用法只提供一个茶杯上个月用来指明fetch到的资源路径,然后返回一个包含响应结果的promise(一个Response对象)。

    它只是一个Http响应并不是真的JSON,为了获取JSON的内容,还需要使用json()方法,在Body的mixin中定义,被Request和Response对象实现。

    带两个参数的示例:

    // Example POST method implementation:
    
    postData('http://example.com/answer', {answer: 42})
      .then(data => console.log(data)) // JSON from `response.json()` call
      .catch(error => console.error(error))
    
    function postData(url, data) {
      // Default options are marked with *
      return fetch(url, {
        body: JSON.stringify(data), // must match 'Content-Type' header
        cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
        credentials: 'same-origin', // include, same-origin, *omit
        headers: {
          'user-agent': 'Mozilla/4.0 MDN Example',
          'content-type': 'application/json'
        },
        method: 'POST', // *GET, POST, PUT, DELETE, etc.
        mode: 'cors', // no-cors, cors, *same-origin
        redirect: 'follow', // manual, *follow, error
        referrer: 'no-referrer', // *client, no-referrer
      })
      .then(response => response.json()) // parses response to JSON
    }

    发送带凭证的请求:

    fetch('https://example.com', {
      credentials: 'include'  
    })

    如果只想在请求URL与调用脚本位于同一起源处时发送凭证,添加credentials:'same-origin'

    // The calling script is on the origin 'https://example.com'
    
    fetch('https://example.com', {
      credentials: 'same-origin'  
    })

    为确保浏览器不在请求中包含凭证,使用omit

    fetch('https://example.com', {
      credentials: 'omit'  
    })

    上传JSON数据示例:

    var url = 'https://example.com/profile';
    var data = {username: 'example'};
    
    fetch(url, {
      method: 'POST', // or 'PUT'
      body: JSON.stringify(data), // data can be `string` or {object}!
      headers: new Headers({
        'Content-Type': 'application/json'
      })
    }).then(res => res.json())
    .catch(error => console.error('Error:', error))
    .then(response => console.log('Success:', response));

    上传文件示例:

    var formData = new FormData();
    var fileField = document.querySelector("input[type='file']");
    
    formData.append('username', 'abc123');
    formData.append('avatar', fileField.files[0]);
    
    fetch('https://example.com/profile/avatar', {
      method: 'PUT',
      body: formData
    })
    .then(response => response.json())
    .catch(error => console.error('Error:', error))
    .then(response => console.log('Success:', response));

    上传多个文件示例:

    var formData = new FormData();
    var photos = document.querySelector("input[type='file'][multiple]");
    
    formData.append('title', 'My Vegas Vacation');
    // formData 只接受文件、Blob 或字符串,不能直接传递数组,所以必须循环嵌入
    for (let i = 0; i < photos.files.length; i++) { 
        formData.append('photo', photos.files[i]); 
    }
    
    fetch('https://example.com/posts', {
      method: 'POST',
      body: formData
    })
    .then(response => response.json())
    .then(response => console.log('Success:', JSON.stringify(response)))
    .catch(error => console.error('Error:', error));

    检测请求是否成功:

    如果网络故障,fetch()promise将会reject戴上一个TypeError对象,虽然这种情况经常遇到权限问题或者是类似问题,如404不是一个网络故障。想精确的判断fetch是否成功,需要promise resolved的情况,此时再判断Response.ok是不是true。

    fetch('flowers.jpg').then(function(response) {
      if(response.ok) {
        return response.blob();
      }
      throw new Error('Network response was not ok.');
    }).then(function(myBlob) { 
      var objectURL = URL.createObjectURL(myBlob); 
      myImage.src = objectURL; 
    }).catch(function(error) {
      console.log('There has been a problem with your fetch operation: ', error.message);
    });

    自定义请求对象:

    除了传给fetch一个资源的地址,还可以通过Request来构造函数来创建一个request对象,然后再传给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

    Request() 和 fetch() 接受同样的参数。你甚至可以传入一个已存在的 request 对象来创造一个拷贝:

    var anotherRequest = new Request(myRequest,myInit);

    Headers示例:

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

    多维数组或者对象字面量:

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

    它的内容可以被获取:

    console.log(myHeaders.has("Content-Type")); // true
    console.log(myHeaders.has("Set-Cookie")); // false
    myHeaders.set("Content-Type", "text/html");
    myHeaders.append("X-Custom-Header", "AnotherValue");
     
    console.log(myHeaders.get("Content-Length")); // 11
    console.log(myHeaders.getAll("X-Custom-Header")); // ["ProcessThisImmediately", "AnotherValue"]
     
    myHeaders.delete("X-Custom-Header");
    console.log(myHeaders.getAll("X-Custom-Header")); // [ ]

    虽然一些操作只能在 ServiceWorkers 中使用,但是它提供了更方便的操作 Headers 的 API。

    如果使用了一个不合法的HTTP Header属性名,那么Headers的方法通常都抛出 TypeError 异常。如果不小心写入了一个不可写的属性,也会抛出一个 TypeError 异常。除此以外的情况,失败了并不抛出异常。例如:

    var myResponse = Response.error();
    try {
      myResponse.headers.set("Origin", "http://mybank.com");
    } catch(e) {
      console.log("Cannot pretend to be a bank!");
    }

    最好在在使用之前检查内容类型 content-type 是否正确,比如:

    fetch(myRequest).then(function(response) {
      if(response.headers.get("content-type") === "application/json") {
        return response.json().then(function(json) {
          // process your JSON further
        });
      } else {
        console.log("Oops, we haven't got JSON!");
      }
    });

    Guard

    由于 Headers 可以在 request 请求中被发送或者在 response 请求中被接收,并且规定了哪些参数是可写的,Headers 对象有一个特殊的 guard 属性。这个属性没有暴露给 Web,但是它影响到哪些内容可以在 Headers 对象中被操作。

    可能的值如下:

    • none:默认的
    • request:从 request 中获得的 headers(Request.headers)只读
    • request-no-cors:从不同域(Request.mode no-cors)的 request 中获得的 headers 只读
    • response:从 response 中获得的 headers(Response.headers)只读
    • immutable:在 ServiceWorkers 中最常用的,所有的 headers 都只读。

    Response 对象

    如上所述,Response 实例是在 fetch() 处理完 promise 之后返回的。

    你会用到的最常见的 response 属性有:

    • Response.status — 整数(默认值为200)为response的状态码。
    • Response.statusText — 字符串(默认值为"OK"),该值与 HTTP 状态码消息对应。
    • Response.ok — 如上所示,该属性是来检查response的状态是否在 200 - 299(包括200 和 299)这个范围内。该属性返回一个布尔值

    它的实例也可用通过 JavaScript 来创建,但只有在 ServiceWorkers 中才真正有用,当使用 respondWith() 方法并提供了一个自定义的 response 来接受 request 时:

    var myBody = new Blob();
    
    addEventListener('fetch', function(event) {
      event.respondWith(new Response(myBody, {
        headers: { "Content-Type" : "text/plain" }
      });
    });

    Response() 构造方法接受两个可选参数—— response 的数据体和一个初始化对象(与Request() 所接受的 init 参数类似。)

    Body

    不管是请求还是响应都能够包含 body 对象。body 也可以是以下任意类型的实例。

    Body 类定义了以下方法(这些方法都被 Request 和Response所实现)以获取 body 内容。这些方法都会返回一个被解析后的Promise对象和数据。

    比起XHR来,这些方法让非文本化的数据使用起来更加简单。

    请求体可以由传入 body 参数来进行设置:

    var form = new FormData(document.getElementById('login-form'));
    fetch("/login", {
      method: "POST",
      body: form
    })

    特性检测

    Fetch API 的支持情况,可以通过检测HeadersRequestResponse 或 fetch()是否在Window 或 Worker 域中。例如:

    if(self.fetch) {
        // run my fetch request here
    } else {
        // do something with XMLHttpRequest?
    }

    Polyfill

    如果要在不支持的浏览器中使用 Fetch,可以使用 Fetch Polyfill

  • 相关阅读:
    zookeeper使用场景
    zookeeper安装配置
    hadoop 远程调试
    deep learning笔记
    Sentiment Analysis(1)-Dependency Tree-based Sentiment Classification using CRFs with Hidden Variables
    PRML阅读笔记 introduction
    Python 学习笔记(2)
    python nltk 学习笔记(5) Learning to Classify Text
    python nltk 学习笔记(4) Writing Structured Programs
    python nltk 学习笔记(3) processing raw text
  • 原文地址:https://www.cnblogs.com/lsb123/p/13170001.html
Copyright © 2011-2022 走看看