fetch()
可讓您發出類似 XMLHttpRequest (XHR) 的網路要求。主要差異在於 Fetch API 使用 Promise,後者提供更簡單的 API,可協助您避免使用 XMLHttpRequest API 中的複雜回呼。
如果您沒用過 Promise 請先參閱 JavaScript Promise 簡介。
基本擷取要求
以下是使用 XMLHttpRequest
和 fetch
實作的範例。我們想要求存取網址、取得回應以及剖析
匯出為 JSON
XMLHttpRequest
XMLHttpRequest
需要兩個事件監聽器來處理成功和錯誤案例,以及對 open()
和 send()
的呼叫。MDN 文件範例。
function reqListener () {
const data = JSON.parse(this.responseText);
console.log(data);
}
function reqError (err) {
console.log('Fetch Error :-S', err);
}
const oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();
擷取
我們的擷取要求如下所示:
fetch('./api/some.json')
.then(response => {
if (response.status !== 200) {
console.log(`Looks like there was a problem. Status Code: ${response.status}`);
return;
}
// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
})
.catch(err => {
console.log('Fetch Error :-S', err);
});
fetch()
要求只需要一個呼叫就能執行與 XHR 相同的工作
範例。為了處理回應,我們會先檢查回應狀態是否為 200,然後將回應解析為 JSON。fetch()
要求的回應是
Stream 物件,也就是說,
我們呼叫了 json()
方法,會傳回 Promise。
串流會以非同步方式發生。
回應中繼資料
上一個範例顯示了 Response 物件的狀態,以及如何將回應解析為 JSON。以下說明如何處理您可能要存取的其他中繼資料,例如標頭:
fetch('users.json').then(response => {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});
回應類型
當我們提出擷取要求時,回應會獲得 response.type
「basic
」,
「cors
」或
「opaque
」。
這些types
會顯示資源的來源,您可以使用這些資源
判斷如何處理回應物件
當瀏覽器要求相同來源的資源時,回應會具有 basic
類型,並限制您可以從回應中查看的內容。
如果對另一個來源的資源發出要求,且該來源會傳回
COR 標頭,則類型為 cors
。cors
回應類似於 basic
回應,但會限制
可查看「Cache-Control
」、「Content-Language
」、「Content-Type
」、「Expires
」和
Last-Modified
和Pragma
。
opaque
回應來自不同的來源,該來源不會傳回 CORS 標頭。由於回應內容不透明,我們無法讀取傳回的資料或查看要求狀態,也就是說,您無法檢查要求是否成功。
您可以為擷取要求定義模式,讓系統只解析特定要求類型。您可以設定的模式如下:
same-origin
只會成功處理同一個來源的素材資源要求,並拒絕所有其他要求。cors
允許要求相同來源及其他來源的資產 會傳回適當的 COR 標頭。cors-with-forced-preflight
會執行預檢 查看 再提出要求no-cors
的用途是向其他沒有 CORS 的來源發出要求 標頭並產生opaque
回應,但如 所述,這並非 都可以使用這項工具
如要定義模式,請在 fetch
要求中新增選項物件做為第二個參數,並在該物件中定義模式:
fetch('http://some-site.com/cors-enabled/some.json', {mode: 'cors'})
.then(response => response.text())
.then(text => {
console.log('Request successful', text);
})
.catch(error => {
log('Request failed', error)
});
承諾鏈結
實現承諾的一大特色是能夠鏈結在一起。對於 fetch()
,這可讓您在擷取要求之間共用邏輯。
如果您使用的是 JSON API,則需要檢查狀態,並剖析每個回應的 JSON。您可以透過在傳回承諾的個別函式中定義狀態和 JSON 剖析,並使用擷取要求只處理最終資料和錯誤情況,藉此簡化程式碼。
function status (response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json (response) {
return response.json()
}
fetch('users.json')
.then(status)
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
}).catch(error => {
console.log('Request failed', error);
});
這個範例定義了 status
函式,用於檢查 response.status
,並傳回已解析的 Promise 做為 Promise.resolve()
,或傳回已拒絕的 Promise 做為 Promise.reject()
。這是 fetch()
鏈結中呼叫的第一個方法。
如果 Promise 已解析,指令碼會呼叫 json()
方法,
從 response.json()
呼叫傳回第二個 Promise,並
物件,當中含有剖析 JSON 檔案。如果剖析失敗,承諾會遭到拒絕,並執行 catch 陳述式。
這個結構可讓您在所有擷取要求中共用邏輯, 維護、讀取及測試程式碼變得更簡單
POST 要求
有時候,網頁應用程式需要使用 POST 方法呼叫 API,並加入一些
參數中。如要這麼做,請在 fetch()
選項中設定 method
和 body
參數:
fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(data => {
console.log('Request succeeded with JSON response', data);
})
.catch(error => {
console.log('Request failed', error);
});
透過擷取要求傳送憑證
如要提出含有憑證 (例如 Cookie) 的擷取要求,請將要求的 credentials
值設為 "include"
:
fetch(url, {
credentials: 'include'
})