fetch()
cho phép bạn thực hiện các yêu cầu mạng tương tự như XMLHttpRequest (XHR). Điểm khác biệt chính là API Tìm nạp sử dụng Lời hứa (Promise) có API đơn giản hơn để giúp bạn tránh các lệnh gọi lại phức tạp trong API XMLHttpRequest.
Nếu bạn chưa từng sử dụng Lời hứa trước đây, hãy xem phần Giới thiệu về JavaScript Promises.
Yêu cầu tìm nạp cơ bản
Dưới đây là ví dụ được triển khai bằng XMLHttpRequest
rồi bằng fetch
. Chúng ta muốn yêu cầu một URL, nhận phản hồi và phân tích cú pháp phản hồi đó dưới dạng JSON.
XMLHttpRequest
XMLHttpRequest
cần có 2 trình nghe để xử lý thành công
và các trường hợp lỗi cũng như lệnh gọi đến open()
và send()
.
Ví dụ trong tài liệu về 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();
Tìm nạp
Yêu cầu tìm nạp của chúng ta sẽ có dạng như sau:
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);
});
Yêu cầu fetch()
chỉ cần một lệnh gọi để thực hiện công việc tương tự như XHR
ví dụ: Để xử lý phản hồi, trước tiên, chúng tôi kiểm tra xem trạng thái phản hồi có phải là
200, sau đó phân tích cú pháp phản hồi dưới dạng JSON. Phản hồi cho yêu cầu fetch()
là một đối tượng Stream, nghĩa là sau khi chúng ta gọi phương thức json()
, một Lời hứa sẽ được trả về.
Luồng dữ liệu này diễn ra không đồng bộ.
Siêu dữ liệu về câu trả lời
Ví dụ trước đã cho thấy trạng thái của đối tượng Phản hồi và cách phân tích cú pháp phản hồi dưới dạng JSON. Sau đây là cách xử lý siêu dữ liệu khác mà bạn có thể cần để truy cập, chẳng hạn như tiêu đề:
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);
});
Loại phản hồi
Khi chúng ta đưa ra yêu cầu tìm nạp, phản hồi sẽ được cung cấp một response.type
trong tổng số "basic
",
"cors
" hoặc
"opaque
".
Các types
này cho biết nguồn gốc của tài nguyên và bạn có thể sử dụng chúng để
xác định cách xử lý đối tượng phản ứng.
Khi trình duyệt yêu cầu một tài nguyên trên cùng một nguồn gốc, phản hồi có một
Nhập basic
có hạn chế về nội dung bạn có thể xem trong câu trả lời.
Nếu một yêu cầu được thực hiện cho một tài nguyên trên một nguồn gốc khác và nguồn gốc đó trả về tiêu đề CORs, thì loại này là cors
. cors
các phản hồi tương tự như phản hồi basic
, nhưng chúng hạn chế các tiêu đề mà bạn
có thể xem Cache-Control
, Content-Language
, Content-Type
, Expires
,
Last-Modified
và Pragma
.
opaque
phản hồi đến từ một nguồn khác không trả về CORS
. Với một câu trả lời không rõ ràng, chúng tôi sẽ không thể
đọc dữ liệu được trả về hoặc xem trạng thái của yêu cầu, tức là bạn không thể kiểm tra
liệu yêu cầu có thành công hay không.
Bạn có thể xác định chế độ cho một yêu cầu tìm nạp để chỉ một số loại yêu cầu nhất định mới được phân giải. Bạn có thể đặt các chế độ như sau:
same-origin
chỉ thành công đối với các yêu cầu tài sản trên cùng một nguồn gốc, và từ chối tất cả các yêu cầu khác.cors
cho phép các yêu cầu đối với các thành phần trên cùng một nguồn gốc và các nguồn gốc khác trả về tiêu đề CORS thích hợp.cors-with-forced-preflight
thực hiện quy trình kiểm tra dấu kiểm trước khi đưa ra bất kỳ yêu cầu nào.no-cors
dùng để đưa ra yêu cầu cho các nguồn gốc khác không có CORS tiêu đề và dẫn đến phản hồiopaque
, nhưng như đã nêu , đây không phải là có thể sử dụng trong phạm vi cửa sổ toàn cục hiện tại.
Để xác định chế độ, hãy thêm một đối tượng tuỳ chọn làm tham số thứ hai trong
Yêu cầu fetch
và xác định chế độ trong đối tượng đó:
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)
});
Xâu chuỗi lời hứa
Một trong những tính năng tuyệt vời của lời hứa là khả năng liên kết các lời hứa với nhau. Đối với fetch()
, điều này cho phép bạn chia sẻ logic trên các yêu cầu tìm nạp.
Nếu đang làm việc với một API JSON, bạn cần kiểm tra trạng thái và phân tích cú pháp JSON cho mỗi phản hồi. Bạn có thể đơn giản hoá mã bằng cách xác định trạng thái và phân tích cú pháp JSON trong các hàm riêng biệt trả về các lời hứa, đồng thời sử dụng yêu cầu tìm nạp để chỉ xử lý dữ liệu cuối cùng và trường hợp lỗi.
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);
});
Ví dụ này xác định một hàm status
kiểm tra response.status
và
trả về một Promise (Lời hứa đã được giải quyết) dưới dạng
Promise.resolve()
,
hoặc Lời hứa bị từ chối dưới dạng
Promise.reject()
.
Đây là phương thức đầu tiên được gọi trong chuỗi fetch()
.
Nếu Lời hứa được phân giải, tập lệnh sẽ gọi phương thức json()
. Phương thức này sẽ trả về một Lời hứa thứ hai từ lệnh gọi response.json()
và tạo một đối tượng chứa JSON đã phân tích cú pháp. Nếu quá trình phân tích cú pháp không thành công, Promise sẽ là
bị từ chối và câu lệnh phát hiện được thực thi.
Cấu trúc này cho phép bạn chia sẻ logic trên tất cả các yêu cầu tìm nạp, giúp mã dễ bảo trì, đọc và kiểm thử hơn.
Yêu cầu POST
Đôi khi, một ứng dụng web cần gọi một API bằng phương thức POST và bao gồm một số
các tham số trong phần nội dung của yêu cầu. Để thực hiện việc này, hãy đặt các tham số method
và body
trong các tuỳ chọn fetch()
:
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);
});
Gửi thông tin đăng nhập cùng với yêu cầu tìm nạp
Để tạo yêu cầu tìm nạp bằng thông tin xác thực như cookie, hãy đặt giá trị credentials
của yêu cầu thành "include"
:
fetch(url, {
credentials: 'include'
})