Lớp học lập trình này nằm trong khoá học Phát triển ứng dụng web tiến bộ do Nhóm đào tạo nhà phát triển của Google xây dựng. Bạn sẽ nhận được nhiều giá trị nhất qua khoá học này nếu thực hiện các lớp học lập trình theo trình tự.
Để biết đầy đủ thông tin chi tiết về khoá học, hãy xem bài viết Tổng quan về việc phát triển ứng dụng web tiến bộ.
Giới thiệu
Lớp học này hướng dẫn bạn cách sử dụng Fetch API, một giao diện đơn giản để tìm nạp tài nguyên và có nhiều điểm cải tiến so với XMLHttpRequest API.
Kiến thức bạn sẽ học được
- Cách sử dụng Fetch API để yêu cầu tài nguyên
- Cách đưa ra yêu cầu GET, HEAD và POST bằng lệnh tìm nạp
- Cách đọc và đặt tiêu đề tuỳ chỉnh
- Mức sử dụng và giới hạn của CORS
Những điều bạn cần biết
- JavaScript và HTML cơ bản
- Làm quen với khái niệm và cú pháp cơ bản của Promise ES2015
Bạn cần có
- Máy tính có quyền truy cập vào thiết bị đầu cuối/vỏ
- Kết nối Internet
- Trình duyệt hỗ trợ Fetch
- Trình chỉnh sửa văn bản
- Node và npm
Lưu ý: Mặc dù Fetch API hiện không được hỗ trợ trong tất cả các trình duyệt, nhưng có một polyfill.
Tải xuống hoặc sao chép kho lưu trữ pwa-training-labs trên github và cài đặt phiên bản LTS của Node.js (nếu cần).
Mở dòng lệnh trên máy tính. Chuyển đến thư mục fetch-api-lab/app/
rồi khởi động một máy chủ phát triển cục bộ:
cd fetch-api-lab/app npm install node server.js
Bạn có thể chấm dứt máy chủ bất cứ lúc nào bằng cách nhấn Ctrl-c
.
Mở trình duyệt rồi chuyển đến localhost:8081/
. Bạn sẽ thấy một trang có các nút để đưa ra yêu cầu (các nút này chưa hoạt động).
Lưu ý: Huỷ đăng ký mọi trình chạy dịch vụ và xoá tất cả bộ nhớ đệm của trình chạy dịch vụ cho localhost để chúng không gây trở ngại cho phòng thí nghiệm. Trong Công cụ của Chrome cho nhà phát triển, bạn có thể thực hiện việc này bằng cách nhấp vào Xoá dữ liệu trang web trong mục Xoá bộ nhớ của thẻ Ứng dụng.
Mở thư mục fetch-api-lab/app/
trong trình chỉnh sửa văn bản mà bạn muốn. Thư mục app/
là nơi bạn sẽ xây dựng phòng thí nghiệm.
Thư mục này chứa:
echo-servers/
chứa các tệp dùng để chạy máy chủ kiểm thửexamples/
chứa các tài nguyên mẫu mà chúng ta sử dụng trong quá trình thử nghiệm với lệnh tìm nạpjs/main.js
là JavaScript chính cho ứng dụng và đây là nơi bạn sẽ viết tất cả mã của mìnhindex.html
là trang HTML chính cho trang web/ứng dụng mẫu của chúng tôipackage-lock.json
vàpackage.json
là các tệp cấu hình cho máy chủ phát triển và các phần phụ thuộc của máy chủ phản hồiserver.js
là một máy chủ phát triển nút
Fetch API có một giao diện tương đối đơn giản. Phần này giải thích cách viết một yêu cầu HTTP cơ bản bằng cách sử dụng lệnh tìm nạp.
Tìm nạp tệp JSON
Trong js/main.js
, nút Fetch JSON (Tìm nạp JSON) của ứng dụng được đính kèm vào hàm fetchJSON
.
Cập nhật hàm fetchJSON
để yêu cầu tệp examples/animals.json
và ghi nhật ký phản hồi:
function fetchJSON() {
fetch('examples/animals.json')
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Tìm nạp JSON. Bảng điều khiển sẽ ghi lại phản hồi tìm nạp.
Giải thích
Phương thức fetch
chấp nhận đường dẫn cho tài nguyên mà chúng ta muốn truy xuất dưới dạng tham số, trong trường hợp này là examples/animals.json
. fetch
trả về một lời hứa phân giải thành một đối tượng Phản hồi. Nếu promise phân giải, phản hồi sẽ được truyền đến hàm logResult
. Nếu lời hứa bị từ chối, catch
sẽ tiếp quản và lỗi sẽ được truyền đến hàm logError
.
Các đối tượng phản hồi đại diện cho phản hồi đối với một yêu cầu. Chúng chứa nội dung phản hồi cũng như các thuộc tính và phương thức hữu ích.
Kiểm thử các phản hồi không hợp lệ
Kiểm tra phản hồi đã ghi trong bảng điều khiển. Lưu ý các giá trị của thuộc tính status
, url
và ok
.
Thay thế tài nguyên examples/animals.json
trong fetchJSON
bằng examples/non-existent.json
. Hàm fetchJSON
được cập nhật giờ đây sẽ có dạng như sau:
function fetchJSON() {
fetch('examples/non-existent.json')
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp lại vào Tìm nạp JSON để thử tìm nạp tài nguyên không tồn tại này.
Quan sát để thấy rằng quá trình tìm nạp đã hoàn tất thành công và không kích hoạt khối catch
. Giờ đây, hãy tìm các thuộc tính status
, URL
và ok
của phản hồi mới.
Giá trị của hai tệp này phải khác nhau (bạn có hiểu lý do không?). Nếu bạn gặp lỗi nào đó trên bảng điều khiển, các giá trị có khớp với bối cảnh của lỗi đó không?
Giải thích
Tại sao phản hồi không thành công không kích hoạt khối catch
? Đây là một lưu ý quan trọng đối với lệnh tìm nạp và lời hứa – các phản hồi không hợp lệ (chẳng hạn như 404) vẫn được phân giải! Một lời hứa tìm nạp chỉ từ chối nếu yêu cầu không thể hoàn tất, vì vậy, bạn phải luôn kiểm tra tính hợp lệ của phản hồi. Chúng ta sẽ xác thực các phản hồi trong phần tiếp theo.
Thông tin khác
Kiểm tra tính hợp lệ của câu trả lời
Chúng ta cần cập nhật mã để kiểm tra tính hợp lệ của các phản hồi.
Trong main.js
, hãy thêm một hàm để xác thực các phản hồi:
function validateResponse(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
Sau đó, hãy thay thế fetchJSON
bằng đoạn mã sau:
function fetchJSON() {
fetch('examples/non-existent.json')
.then(validateResponse)
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Tìm nạp JSON. Kiểm tra bảng điều khiển. Giờ đây, phản hồi cho examples/non-existent.json
sẽ kích hoạt khối catch
.
Thay thế examples/non-existent.json
trong hàm fetchJSON
bằng examples/animals.json
ban đầu. Hàm được cập nhật giờ đây sẽ có dạng như sau:
function fetchJSON() {
fetch('examples/animals.json')
.then(validateResponse)
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Tìm nạp JSON. Bạn sẽ thấy rằng phản hồi đang được ghi nhật ký thành công như trước.
Giải thích
Giờ đây, khi chúng ta đã thêm chế độ kiểm tra validateResponse
, các phản hồi không hợp lệ (chẳng hạn như 404) sẽ gây ra lỗi và catch
sẽ tiếp quản. Điều này cho phép chúng tôi xử lý các phản hồi không thành công và ngăn các phản hồi không mong muốn lan truyền xuống chuỗi tìm nạp.
Đọc câu trả lời
Các phản hồi tìm nạp được biểu thị dưới dạng ReadableStreams (streams spec) và phải được đọc để truy cập vào nội dung của phản hồi. Các đối tượng phản hồi có phương thức để thực hiện việc này.
Trong main.js
, hãy thêm hàm readResponseAsJSON
bằng đoạn mã sau:
function readResponseAsJSON(response) {
return response.json();
}
Sau đó, thay thế hàm fetchJSON
bằng mã sau:
function fetchJSON() {
fetch('examples/animals.json') // 1
.then(validateResponse) // 2
.then(readResponseAsJSON) // 3
.then(logResult) // 4
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Tìm nạp JSON. Kiểm tra bảng điều khiển để xem JSON từ examples/animals.json
có đang được ghi nhật ký hay không (thay vì đối tượng Phản hồi).
Giải thích
Hãy cùng xem điều gì đang xảy ra.
Bước 1. Tìm nạp được gọi trên một tài nguyên, examples/animals.json
. Hàm tìm nạp trả về một lời hứa phân giải thành một đối tượng Phản hồi. Khi lời hứa được thực hiện, đối tượng phản hồi sẽ được truyền đến validateResponse
.
Bước 2. validateResponse
kiểm tra xem phản hồi có hợp lệ hay không (có phải là 200 không?). Nếu không, một lỗi sẽ xảy ra, bỏ qua các khối then
còn lại và kích hoạt khối catch
. Điều này đặc biệt quan trọng. Nếu không có bước kiểm tra này, các phản hồi không hợp lệ sẽ được truyền xuống chuỗi và có thể làm hỏng mã sau này có thể dựa vào việc nhận được phản hồi hợp lệ. Nếu phản hồi hợp lệ, phản hồi đó sẽ được truyền đến readResponseAsJSON
.
Bước 3. readResponseAsJSON
đọc nội dung phản hồi bằng phương thức Response.json(). Phương thức này trả về một lời hứa phân giải thành JSON. Sau khi lời hứa này được thực hiện, dữ liệu JSON sẽ được truyền đến logResult
. (Nếu lời hứa từ response.json()
bị từ chối, khối catch
sẽ được kích hoạt.)
Bước 4. Cuối cùng, dữ liệu JSON từ yêu cầu ban đầu đến examples/animals.json
sẽ được logResult
ghi lại.
Thông tin khác
Không chỉ giới hạn ở JSON. Trong ví dụ này, chúng ta sẽ tìm nạp một hình ảnh và thêm hình ảnh đó vào trang.
Trong main.js
, hãy viết một hàm showImage
có mã sau:
function showImage(responseAsBlob) {
const container = document.getElementById('img-container');
const imgElem = document.createElement('img');
container.appendChild(imgElem);
const imgUrl = URL.createObjectURL(responseAsBlob);
imgElem.src = imgUrl;
}
Sau đó, hãy thêm một hàm readResponseAsBlob
đọc các phản hồi dưới dạng Blob:
function readResponseAsBlob(response) {
return response.blob();
}
Cập nhật hàm fetchImage
bằng mã sau:
function fetchImage() {
fetch('examples/fetching.jpg')
.then(validateResponse)
.then(readResponseAsBlob)
.then(showImage)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Tìm nạp hình ảnh. Bạn sẽ thấy một chú chó đáng yêu đang tha một chiếc gậy trên trang (đây là một trò đùa về việc tha đồ vật!).
Giải thích
Trong ví dụ này, một hình ảnh đang được tìm nạp, examples/fetching.jpg
. Giống như trong bài tập trước, phản hồi được xác thực bằng validateResponse
. Sau đó, phản hồi sẽ được đọc dưới dạng Blob (thay vì JSON như trong phần trước). Một phần tử hình ảnh được tạo và thêm vào trang, đồng thời thuộc tính src
của hình ảnh được đặt thành một URL dữ liệu đại diện cho Blob.
Lưu ý: Phương thức createObjectURL()
của đối tượng URL được dùng để tạo một URL dữ liệu đại diện cho Blob. Đây là điều quan trọng cần lưu ý. Bạn không thể đặt trực tiếp nguồn của hình ảnh thành Blob. Blob phải được chuyển đổi thành một URL dữ liệu.
Thông tin khác
Phần này là một thử thách không bắt buộc.
Cập nhật hàm fetchText
thành
- tìm nạp
/examples/words.txt
- xác thực phản hồi bằng
validateResponse
- đọc phản hồi dưới dạng văn bản (gợi ý: xem Response.text())
- và hiển thị văn bản trên trang
Bạn có thể dùng hàm showText
này làm hàm trợ giúp để hiển thị văn bản cuối cùng:
function showText(responseAsText) {
const message = document.getElementById('message');
message.textContent = responseAsText;
}
Lưu tập lệnh và làm mới trang. Nhấp vào Lấy văn bản. Nếu đã triển khai fetchText
đúng cách, bạn sẽ thấy văn bản được thêm trên trang.
Lưu ý: Mặc dù bạn có thể muốn tìm nạp HTML và nối HTML đó bằng thuộc tính innerHTML
, nhưng hãy cẩn thận. Điều này có thể khiến trang web của bạn gặp phải các cuộc tấn công chèn tập lệnh vào nhiều trang web!
Thông tin khác
Theo mặc định, lệnh tìm nạp sử dụng phương thức GET để truy xuất một tài nguyên cụ thể. Tuy nhiên, lệnh tìm nạp cũng có thể sử dụng các phương thức HTTP khác.
Gửi yêu cầu HEAD
Thay thế hàm headRequest
bằng mã sau:
function headRequest() {
fetch('examples/words.txt', {
method: 'HEAD'
})
.then(validateResponse)
.then(readResponseAsText)
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào HEAD request (yêu cầu HEAD). Quan sát thấy nội dung văn bản đã ghi nhật ký đang trống.
Giải thích
Phương thức fetch
có thể nhận tham số không bắt buộc thứ hai là init
. Tham số này cho phép định cấu hình yêu cầu tìm nạp, chẳng hạn như phương thức yêu cầu, chế độ lưu vào bộ nhớ đệm, thông tin đăng nhập, và nhiều thông số khác.
Trong ví dụ này, chúng ta đặt phương thức yêu cầu tìm nạp thành HEAD bằng cách sử dụng tham số init
. Yêu cầu HEAD cũng giống như yêu cầu GET, ngoại trừ nội dung phản hồi là trống. Bạn có thể dùng loại yêu cầu này khi chỉ muốn có siêu dữ liệu về một tệp nhưng không cần truyền tất cả dữ liệu của tệp đó.
Không bắt buộc: Tìm kích thước của một tài nguyên
Hãy xem Tiêu đề của phản hồi tìm nạp cho examples/words.txt
để xác định kích thước của tệp.
Cập nhật hàm headRequest
để ghi nhật ký thuộc tính content-length
của phản hồi headers
(gợi ý: xem tài liệu về tiêu đề và phương thức get).
Sau khi bạn cập nhật mã, hãy lưu tệp và làm mới trang. Nhấp vào HEAD request (yêu cầu HEAD). Bảng điều khiển sẽ ghi lại kích thước (tính bằng byte) của examples/words.txt
.
Giải thích
Trong ví dụ này, phương thức HEAD được dùng để yêu cầu kích thước (tính bằng byte) của một tài nguyên (được biểu thị trong tiêu đề content-length
) mà không thực sự tải chính tài nguyên đó. Trên thực tế, bạn có thể dùng thông tin này để xác định xem có nên yêu cầu toàn bộ tài nguyên hay không (hoặc thậm chí là cách yêu cầu tài nguyên).
Không bắt buộc: Tìm kích thước của examples/words.txt
bằng một phương thức khác và xác nhận rằng kích thước đó khớp với giá trị trong tiêu đề phản hồi (bạn có thể tìm cách thực hiện việc này cho hệ điều hành cụ thể của mình – điểm cộng nếu bạn sử dụng dòng lệnh!).
Thông tin khác
Fetch cũng có thể gửi dữ liệu bằng các yêu cầu POST.
Thiết lập máy chủ lặp lại
Đối với ví dụ này, bạn cần chạy một máy chủ lặp lại. Từ thư mục fetch-api-lab/app/
, hãy chạy lệnh sau (nếu dòng lệnh của bạn bị chặn bởi máy chủ localhost:8081
, hãy mở một cửa sổ hoặc thẻ dòng lệnh mới):
node echo-servers/cors-server.js
Lệnh này khởi động một máy chủ đơn giản tại localhost:5000/
, máy chủ này sẽ lặp lại các yêu cầu được gửi đến.
Bạn có thể chấm dứt máy chủ này bất cứ lúc nào bằng cách nhấn vào ctrl+c
.
Đưa ra yêu cầu POST
Thay thế hàm postRequest
bằng mã sau (nhớ xác định hàm showText
trong phần 4 nếu bạn chưa hoàn thành phần này):
function postRequest() {
fetch('http://localhost:5000/', {
method: 'POST',
body: 'name=david&message=hello'
})
.then(validateResponse)
.then(readResponseAsText)
.then(showText)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Nhấp vào Yêu cầu POST. Quan sát yêu cầu đã gửi được phản hồi trên trang. Phần này phải chứa tên và thông báo (xin lưu ý rằng chúng tôi chưa nhận được dữ liệu từ biểu mẫu).
Giải thích
Để thực hiện yêu cầu POST bằng lệnh tìm nạp, chúng ta sử dụng tham số init
để chỉ định phương thức (tương tự như cách chúng ta đặt phương thức HEAD trong phần trước). Đây cũng là nơi chúng ta đặt nội dung của yêu cầu, trong trường hợp này là một chuỗi đơn giản. Phần nội dung là dữ liệu mà chúng ta muốn gửi.
Lưu ý: Trong quá trình phát hành công khai, hãy nhớ luôn mã hoá mọi dữ liệu nhạy cảm của người dùng.
Khi dữ liệu được gửi dưới dạng yêu cầu POST đến localhost:5000/
, yêu cầu đó sẽ được phản hồi lại. Sau đó, phản hồi sẽ được xác thực bằng validateResponse
, đọc dưới dạng văn bản và hiển thị trên trang.
Trên thực tế, máy chủ này sẽ đại diện cho một API của bên thứ ba.
Không bắt buộc: Sử dụng giao diện FormData
Bạn có thể dùng giao diện FormData để dễ dàng lấy dữ liệu từ biểu mẫu.
Trong hàm postRequest
, hãy tạo một đối tượng FormData
mới từ phần tử biểu mẫu msg-form
:
const formData = new FormData(document.getElementById('msg-form'));
Sau đó, hãy thay thế giá trị của tham số body
bằng biến formData
.
Lưu tập lệnh và làm mới trang. Điền thông tin vào biểu mẫu (các trường Tên và Thông báo) trên trang, rồi nhấp vào yêu cầu ĐĂNG. Quan sát nội dung biểu mẫu xuất hiện trên trang.
Giải thích
Hàm khởi tạo FormData
có thể nhận form
HTML và tạo một đối tượng FormData
. Đối tượng này được điền sẵn bằng các khoá và giá trị của biểu mẫu.
Thông tin khác
Khởi động máy chủ lặp lại không có CORS
Dừng máy chủ lặp lại trước đó (bằng cách nhấn ctrl+c
trên dòng lệnh) và khởi động một máy chủ lặp lại mới từ thư mục fetch-lab-api/app/
bằng cách chạy lệnh sau:
node echo-servers/no-cors-server.js
Lệnh này thiết lập một máy chủ phản hồi đơn giản khác, lần này là tại localhost:5001/
. Tuy nhiên, máy chủ này không được định cấu hình để chấp nhận các yêu cầu từ nhiều nguồn.
Tìm nạp từ máy chủ mới
Giờ đây, khi máy chủ mới đang chạy ở localhost:5001/
, chúng ta có thể gửi một yêu cầu tìm nạp đến máy chủ đó.
Cập nhật hàm postRequest
để tìm nạp từ localhost:5001/
thay vì localhost:5000/
. Sau khi bạn cập nhật mã, hãy lưu tệp, làm mới trang rồi nhấp vào Yêu cầu POST.
Bạn sẽ gặp lỗi trong bảng điều khiển cho biết rằng yêu cầu trên nhiều nguồn gốc bị chặn vì thiếu tiêu đề CORS Access-Control-Allow-Origin
.
Cập nhật fetch
trong hàm postRequest
bằng mã sau. Mã này sử dụng chế độ no-cors (như nhật ký lỗi đề xuất) và xoá các lệnh gọi đến validateResponse
và readResponseAsText
(xem phần giải thích bên dưới):
function postRequest() {
const formData = new FormData(document.getElementById('msg-form'));
fetch('http://localhost:5001/', {
method: 'POST',
body: formData,
mode: 'no-cors'
})
.then(logResult)
.catch(logError);
}
Lưu tập lệnh và làm mới trang. Sau đó, hãy điền thông tin vào biểu mẫu thông báo rồi nhấp vào Yêu cầu POST.
Quan sát đối tượng phản hồi được ghi nhật ký trong bảng điều khiển.
Giải thích
Fetch (và XMLHttpRequest) tuân theo chính sách cùng nguồn. Điều này có nghĩa là trình duyệt hạn chế các yêu cầu HTTP từ nhiều nguồn trong tập lệnh. Yêu cầu trên nhiều nguồn gốc xảy ra khi một miền (ví dụ: http://foo.com/
) yêu cầu một tài nguyên từ một miền riêng biệt (ví dụ: http://bar.com/
).
Lưu ý: Các hạn chế đối với yêu cầu từ nhiều nguồn thường gây nhầm lẫn. Nhiều tài nguyên như hình ảnh, biểu định kiểu và tập lệnh được tìm nạp trên nhiều miền (tức là trên nhiều nguồn). Tuy nhiên, đây là những trường hợp ngoại lệ đối với chính sách cùng nguồn gốc. Các yêu cầu trên nhiều nguồn gốc vẫn bị hạn chế từ trong tập lệnh.
Vì máy chủ của ứng dụng có số cổng khác với 2 máy chủ lặp lại, nên các yêu cầu đến một trong 2 máy chủ lặp lại này được coi là yêu cầu từ nhiều nguồn. Tuy nhiên, máy chủ phản hồi đầu tiên chạy trên localhost:5000/
được định cấu hình để hỗ trợ CORS (bạn có thể mở echo-servers/cors-server.js
và kiểm tra cấu hình). Máy chủ phản hồi mới, chạy trên localhost:5001/
, không phải là (đó là lý do chúng ta gặp lỗi).
Việc sử dụng mode: no-cors
cho phép tìm nạp một phản hồi mờ. Điều này cho phép sử dụng để nhận được phản hồi, nhưng ngăn chặn việc truy cập vào phản hồi bằng JavaScript (đó là lý do chúng ta không thể sử dụng validateResponse
, readResponseAsText
hoặc showResponse
). Phản hồi vẫn có thể được sử dụng bởi các API khác hoặc được lưu vào bộ nhớ đệm bởi một worker dịch vụ.
Sửa đổi tiêu đề của yêu cầu
Fetch cũng hỗ trợ việc sửa đổi tiêu đề yêu cầu. Dừng máy chủ lặp lại localhost:5001
(không có CORS) và khởi động lại máy chủ lặp lại localhost:5000
(CORS) từ phần 6:
node echo-servers/cors-server.js
Khôi phục phiên bản trước của hàm postRequest
tìm nạp từ localhost:5000/
:
function postRequest() {
const formData = new FormData(document.getElementById('msg-form'));
fetch('http://localhost:5000/', {
method: 'POST',
body: formData
})
.then(validateResponse)
.then(readResponseAsText)
.then(showText)
.catch(logError);
}
Giờ đây, hãy sử dụng giao diện Tiêu đề để tạo một đối tượng Tiêu đề bên trong hàm postRequest
có tên là messageHeaders
với tiêu đề Content-Type
bằng application/json
.
Sau đó, hãy đặt thuộc tính headers
của đối tượng init
thành biến messageHeaders
.
Cập nhật thuộc tính body
thành một đối tượng JSON được chuyển đổi thành chuỗi, chẳng hạn như:
JSON.stringify({ lab: 'fetch', status: 'fun' })
Sau khi bạn cập nhật mã, hãy lưu tệp và làm mới trang. Sau đó, nhấp vào POST Request (Yêu cầu POST).
Lưu ý rằng yêu cầu được phản hồi hiện có Content-Type
là application/json
(thay vì multipart/form-data
như trước đây).
Giờ hãy thêm một tiêu đề Content-Length
tuỳ chỉnh vào đối tượng messageHeaders
và chỉ định một kích thước tuỳ ý cho yêu cầu.
Sau khi bạn cập nhật mã, hãy lưu tệp, làm mới trang rồi nhấp vào POST Request (Yêu cầu POST). Lưu ý rằng tiêu đề này không được sửa đổi trong yêu cầu được lặp lại.
Giải thích
Giao diện Tiêu đề cho phép tạo và sửa đổi các đối tượng Tiêu đề. Một số tiêu đề, chẳng hạn như Content-Type
, có thể được sửa đổi bằng lệnh tìm nạp. Những tệp khác, chẳng hạn như Content-Length
, được bảo vệ và không thể sửa đổi (vì lý do bảo mật).
Đặt tiêu đề yêu cầu tuỳ chỉnh
Fetch hỗ trợ việc đặt tiêu đề tuỳ chỉnh.
Xoá tiêu đề Content-Length
khỏi đối tượng messageHeaders
trong hàm postRequest
. Thêm tiêu đề tuỳ chỉnh X-Custom
với một giá trị tuỳ ý (ví dụ: "X-CUSTOM': 'hello world'
).
Lưu tập lệnh, làm mới trang rồi nhấp vào Yêu cầu POST.
Bạn sẽ thấy rằng yêu cầu được phản hồi có thuộc tính X-Custom
mà bạn đã thêm.
Bây giờ, hãy thêm tiêu đề Y-Custom
vào đối tượng Tiêu đề. Lưu tập lệnh, làm mới trang rồi nhấp vào Yêu cầu POST.
Bạn sẽ gặp một lỗi tương tự như sau trong bảng điều khiển:
Fetch API cannot load http://localhost:5000/. Request header field y-custom is not allowed by Access-Control-Allow-Headers in preflight response.
Giải thích
Giống như các yêu cầu nhiều nguồn gốc, máy chủ mà từ đó tài nguyên được yêu cầu phải hỗ trợ các tiêu đề tuỳ chỉnh. Trong ví dụ này, máy chủ lặp lại của chúng tôi được định cấu hình để chấp nhận tiêu đề X-Custom
nhưng không chấp nhận tiêu đề Y-Custom
(bạn có thể mở echo-servers/cors-server.js
và tìm Access-Control-Allow-Headers
để tự xem). Bất cứ khi nào bạn đặt một tiêu đề tuỳ chỉnh, trình duyệt sẽ thực hiện một quy trình kiểm tra tiền kiểm. Điều này có nghĩa là trước tiên, trình duyệt sẽ gửi một yêu cầu OPTIONS đến máy chủ để xác định những phương thức và tiêu đề HTTP mà máy chủ cho phép. Nếu máy chủ được định cấu hình để chấp nhận phương thức và tiêu đề của yêu cầu ban đầu, thì yêu cầu đó sẽ được gửi, nếu không thì sẽ xảy ra lỗi.
Thông tin khác
Đoạn mã giải pháp
Để lấy bản sao của đoạn mã đang hoạt động, hãy chuyển đến thư mục solution.
Giờ đây, bạn đã biết cách sử dụng Fetch API!
Tài nguyên
Để xem tất cả các lớp học lập trình trong khoá đào tạo PWA, hãy xem Lớp học lập trình chào mừng cho khoá học này/