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 表示如何處理緩存, 遵照 http 規範, 擁有以下幾種值:json
這是一個比較基本的案例,這裏爲了看的清楚,沒有處理 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 )爲以下三種之一:緩存
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());
}
複製代碼
初次寫帖,若有錯誤或不嚴謹的地方,請務必給予指正,謝謝
參考: