使用更優雅的非同步請求API——fetch
如果你還不知道fetch是什麼,那至少你應該知道XMLHttpRequest,我們接下來就從XMLHttpRequest講起。
XMLHttpRequest是一個Javascript物件,用於在後臺與伺服器交換資料。它最初由微軟設計,隨後被廣泛採納。 如今,該物件已經被 W3C 組織標準化,受到了所有現代瀏覽器的支援。
當我們想要使用XMLHttpRequest傳送一個請求時,通常這樣來做:
首先建立一個 XMLHttpRequest 例項:
var xmlhttp = new XMLHttpRequest()
之後使用open方法初始化一個請求:
let url = location。herf;
xmlhttp。open(‘get’, url, true);
定義回撥函式,只要XMLHttpRequest。readyState 屬性發生變化,就會觸發readystatechange事件,同時有一個事件處理回撥函式被執行:
xmlhttp。onreadystatechange = function () {
if(xmlhttp。readyState === XMLHttpRequest。DONE && xmlhttp。status === 200) console。log(xmlhttp。responseText);
};
最後傳送請求:
xmlhttp。send();
這樣就完成了一個基本的獲取資源的請求。 完整的指令碼如下,開啟瀏覽器除錯工具,執行這段指令碼的話,你會看到獲取到的頁面原始碼。
var url = location。herf;
xmlhttp。open(‘get’, url, true);
xmlhttp。onreadystatechange = function () {
if(xmlhttp。readyState === XMLHttpRequest。DONE && xmlhttp。status === 200) console。log(xmlhttp。responseText);
};
xmlhttp。send();
可能對於一些剛入門的人來說,關於 XMLHttpRequest 的使用方法也並不熟悉,畢竟很多人和我一樣相較於原生js,jQuery寫的要更多些。所以我們也可以先回顧下 jQuery 的 ajax 介面。
在 ajax 中, 我們傳送一條請求時通常這樣來寫:
$。ajax({
type: ‘get’,
url: location。herf,
success: function(data){
console。log(data);
}
})
我們的知乎也使用了jQuery,複製這段程式碼貼到控制檯執行後,也可以看到打印出來的頁面原始碼。
到這裡我們已經使用 XMLHttpRequest 與 ajax 實現獲取非同步資源了。那麼,如果使用 fetch API 的話,這個步驟會是怎樣的呢?
其實很簡單,只需要像下面這樣:
fetch(location。herf, {
method: “get”
})。then(function(response) {
return response。text()
})。then(function(body) {
console。log(body)
})
在你的瀏覽器中執行此段指令碼,同樣會打印出本頁原始碼。我們使用了這段程式碼實現了和上面 XMLHttpRequset 與 ajax 示例指令碼相同的功能。
那麼我們回過頭來,仔細看一下這段fetch指令碼:
首先是 fetch() 方法。
fetch(input, init)
這個方法接受兩個引數:
input
定義要獲取的資源。可以是一個 USVString 字串,包含要獲取資源的 URL。 也可以是一個 Request 物件。
init
這個引數是可選的,它傳入一個配置項物件,可以用它來包括所對請求進行設定。
簡單地說,input 引數就相當於我們使用 ajax 時傳入的url。 那 ajax 的 type 引數在哪裡配置呢?答案當然是在另一個引數 init 裡。 init可以配置其他請求相關引數,包括:
method: 請求使用的方法,如 GET、POST。
headers: 請求的頭資訊,形式為 Headers 物件或 ByteString。
body: 請求的 body 資訊,可能是一個 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 物件。(如果是 GET 或 HEAD 方法,則不能包含 body 資訊)
mode: 請求的模式,如 cors、 no-cors 或者 same-origin。
credentials: 請求的 credentials,如 omit、same-origin 或者 include。
cache: 請求的 cache 模式: default, no-store, reload, no-cache, force-cache, or only-if-cached。
現在我們配置好了請求,可是還有回撥函式呢?ajax 有 success 欄位,XMLHttpRequest 有 onstatechange 方法,fetch為我們實現了什麼?
從上面的 fetch 例項中,顯而易見的,他的回撥是在 then 中執行的。
說到這裡,我們不得不提一個 es6 中新引入的概念: Promise。
ES6的Promise物件是一個建構函式,用來生成Promise例項。下面是Promise物件的基本用法。
var promise = new Promise(function(resolve, reject) {
if (/* 非同步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise。then(function(value) {
// success
}, function(value) {
// failure
});
上面程式碼中,Promise建構函式接受一個函式作為引數,該函式的兩個引數分別是resolve方法和reject方法。如果非同步操作成功,則用resolve方法將Promise物件的狀態變為“成功”(即從pending變為resolved);如果非同步操作失敗,則用reject方法將狀態變為“失敗”(即從pending變為rejected)。
Promise物件使用then方法添加回調函式。then方法可以接受兩個回撥函式,第一個是非同步操作成功時(變為resolved狀態)時的回撥函式,第二個是非同步操作失敗(變為rejected)時的回撥函式(可以省略)。一旦狀態改變,就呼叫相應的回撥函式。
瞭解了以上內容基本上就能解決我們關於 fetch 使用的疑惑了,想要深入瞭解 Promise 的話可以看這裡。
回到我們的fetch。fetch 方法返回的便是為一個 Promise,resolve 時回傳 Response 物件。因此,我們可以用promise的 then 方法直接以鏈式操作的形式來設定 fetch 回撥。
使用形式如下:
fetch(input, init)。then(function(response) { /*請求成功回撥*/ });`
到這裡我們對 fetch 有了一個大致的瞭解, 你可能已經迫不及待想要試一試了。但是,一個不幸的訊息是,目前各主流瀏覽器對 fetch 的支援情況不是很好。
不過,我們可以使用Fetch Polyfil來實現 fetch 功能。
關於fetch polyfil的使用方法github上有詳細介紹,為了方便大家瞭解,我在這裡簡單講述一下。
以下使用方法基於node環境及ES2015:
安裝:
npm install whatwg-fetch ——save
如果你的瀏覽器版本太低,不支援Promise,那你還需要安裝:
npm install promise-polyfill ——save-exact
或者
npm install core-js ——save
在檔案中引入:
import ‘whatwg-fetch’;
import Promise from ‘promise-polyfill’;
或者
import ‘whatwg-fetch’;
import ‘core-js/es6/promise’;
到這裡就可以正常的使用 fetch API 了。
這裡檢視更多關於 fetch API 的資訊
最後,如果想使用 fetch 傳送 jsonp 格式請求,這裡有一個庫 fetch-jsonp
只需要在fetch的基礎上安裝fetch-jsonp 然後在檔案中引入就可以正常使用了:
npm install fetch-jsonp
import fetchJsonp from ‘fetch-jsonp’;
fetchJsonp(‘/users。jsonp’)
。then(function(response) {
return response。json()
})。then(function(json) {
console。log(‘parsed json’, json)
})。catch(function(ex) {
console。log(‘parsing failed’, ex)
})
從現在開始,愉快的使用fetch API 吧~