Fetch 的實例講解

簡介

Fetch API 提供了一個 JavaScript接口,用於訪問和操縱 HTTP 管道的部分,例如請求和響應。它還提供了一個全局 fetch()方法,該方法提供了一種簡單,合乎邏輯的方式來跨網絡異步獲取資源。javascript

fetch() 必須接受一個參數---路徑。不管請求成功與否,它都返回一個 Promise 對象,resolve 對應請求的 Response。另外你還能夠設置第二個參數(可選的參數)options(經常使用配置以下,具體詳情參見 Request)。java

配置

options={
    // 請求方式 GET,POST,等
    method: "GET", 
    
    // 請求頭headers 
    headers: {
        Accept: 'application/json, text/plain, */*',
        'Content-Type': 'application/json;charset=UTF-8', 
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
	},
	
    // omit: 從不發送cookies.
    // same-origin 只有當URL與響應腳本同源才發送 cookies
    // include 老是發送請求資源域在本地的 cookies 驗證信息
    credentials: 'include'//包含請求的模式 (例如: cors, no-cors, same-origin, navigate)
    //no-cors: 經常使用於跨域請求不帶CORS響應頭場景
    //cors表示同域和帶有CORS響應頭的跨域下可請求成功. 其餘請求將被拒絕
    mode: 'cors'//包含請求的緩存模式 (例如: default, reload, no-cache).具體參數見下面(cache參數)
    cache: 'default'
}
複製代碼
cache參數

cache 表示如何處理緩存, 遵照 http 規範, 擁有以下幾種值:json

  1. default: 瀏覽器從 HTTP 緩存中尋找匹配的請求.
  2. no-store: 瀏覽器在不先查看緩存的狀況下從遠程服務器獲取資源,而且不會使用下載的資源更新緩存
  3. reload: 請求以前將忽略 http 緩存的存在, 但請求拿到響應後, 它將主動更新 http 緩存.
  4. no-cache: 若是存在緩存, 那麼 fetch 將發送一個條件查詢 request 和一個正常的 request , 拿到響應後, 它會更新http緩存.
  5. force-cache: 瀏覽器在其HTTP緩存中查找匹配的請求。
    • 若是存在匹配,新鮮或過期,則將從緩存中返回。
    • 若是沒有匹配,瀏覽器將發出正常請求,並使用下載的資源更新緩存
  6. only-if-cached: fetch 強行取緩存,( 即便緩存過時了也從緩存取). 若是沒有緩存, 瀏覽器將返回錯誤

案例

這是一個比較基本的案例,這裏爲了看的清楚,沒有處理 catch 問題 。segmentfault

var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1561&rn=5&t=1551165472017';
fetch(url).then(function(response) {
  return response;
}).then(function(data) {
  console.log(data);
})
複製代碼

能夠本身動手把這個代碼直接貼到控制檯中 , 這裏爲了防止同源策略,而且看到更詳細的數據咱們最好在 https://zhidao.baidu.com 內的控制檯中輸入。若是在其餘的頁面咱們應該在 fetch 方法的第二個參數中加上{ mode: "no-cors" }。爲了看的更加清楚,我貼出這兩種狀況的打印結果,以下所示:api

在 https://zhidao.baidu.com 網頁控制檯輸入的地址跨域

在其餘網頁控制檯輸入的地址promise

咱們會發現兩個打印結果基本不一樣,首先跨域打印的結果中不少數據都是空的,另外咱們也發現其中 type 也不相同,這裏介紹下 response.type。瀏覽器

fetch請求的響應類型( response.type )爲以下三種之一:緩存

  • basic,同域下, 響應類型爲 「basic」。
  • cors,跨域下,返回 cors 響應頭, 響應類型爲 「cors」。
  • opaque,跨域下, 服務器沒有返回 cors 響應頭, 響應類型爲 「opaque」。

fetch設了{mode='no-cors'}表示不垮域,能夠請求成功,但拿不到服務器返回數據服務器

看到這裏,心急的同窗會發現,其實如今數據仍是沒有拿到,咱們僅僅只是拿到了個 Response 對象。那麼如何拿到數據呢?

瞧好:

var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1561&rn=5&t=1551165472017';
fetch(url).then(function(response) {
  //經過 response 原型上的 json 方法拿到數據,在返回出去
  return response.json();
}).then(function(data) {
  // 接收到 data 打印出來
  console.log(data);
})
複製代碼

經過 response 原型上的 json 方法拿到數據,在返回出去。response 原型打印以下:

這裏要注意的是 response .json / response.text 方法只能使用一個而且只能使用一次,同時使用兩個,或則使用兩次都會報以下錯誤:

Uncaught (in promise) TypeError: Failed to execute 'json' on 'Response': body stream is locked

爲何不能使用兩次?

數據流只能讀取一次,一旦讀取,數據流變空,再次讀取會報錯。可使用 response.clone() 複製一個副本。

爲何只能讀取一次?

答案還在查尋中,同時也但願知道的讀者可以指點一下。

上面的寫法,看起來有回調,又有鏈式調用,咱們試着換個新寫法,這裏使用 async/await 來實現:

var url = 'https://zhidao.baidu.com/question/api/hotword?pn=1&rn=5&t=1551191647420';
let getData = async () => {
    let response = await fetch(url);
    let data = response.json();
    console.log(data)
}
複製代碼

打印 data 以下:

這裏 data 是一個 Promise 對象,因爲他的內部變量[[PromiseValue]]在外部沒法獲得,只能在 then 中獲取,因此在後面加上 then 獲取 data

let response = await fetch(url);
let data = response.json();
data.then((res)=>{
  console.log(res)
})
// 搞定 res 就是咱們要的數據拉
複製代碼

封裝

咱們經過 fetch 來作個簡易的 request 封裝,順便把 options 再回顧一遍,不少配置在實際中多是不須要的,都有默認配置(options 的默認配置在下面括號中)。

function request(url, data = {}) {
  // options配置的默認選項在括號中
    return fetch(url, {
        method: "POST", //(GET), POST, PUT, DELETE, etc
        mode: "cors", // (same-origin), no-cors, cors
        cache: "no-cache", // (default), no-cache, reload, force-cache, only-if-cached
        credentials: "same-origin", //(same-origin), include, omit
        headers: {
            "Content-Type": "application/json",
            // "Content-Type": "application/x-www-form-urlencoded",
        },
        redirect: "follow", //(follow), manual, error
        referrer: "no-referrer", //(client), no-referrer
        body: JSON.stringify(data), // 這裏格式要與 "Content-Type" 同步
    })
    .then(response => response.json());
}
複製代碼

最後

初次寫帖,若有錯誤或不嚴謹的地方,請務必給予指正,謝謝

參考:

相關文章
相關標籤/搜索