Ky là một thư viện HTTP client nhỏ gọn và thanh lịch dựa trên trình duyệt Fetch API
Ky hướng đến modern browsers và Deno. Đối với các trình duyệt cũ hơn, bạn sẽ cần biên dịch và sử dụng một fetch polyfill và globalThis polyfill. Đối với nhu cầu đa nền tảng (Node.js + trình duyệt, như SSR), hãy kiểm tra ky-universal.
Nó chỉ là một tập tin nhỏ mà không có sự phụ thuộc.
Ưu điểm so với fetch
thông thường
- Giao diện đơn giản hơn
- Phím tắt phương thức (
ky.post()
) - Xem mã lỗi không phải là mã trạng thái 2xx như lỗi (sau khi được chuyển hướng)
- Thử lại các yêu cầu thất bại
- Tùy chọn JSON
- Hỗ trợ thời gian chờ
- Tùy chọn tiền tố URL
- Các phiên bản với các giá trị mặc định tùy chỉnh
- Hooks (kỹ thuật treo)
Cài Đặt
npm install ky
Tải về
CDN
Sử Dụng
import ky from 'ky';
const json = await ky.post('https://example.com', {json: {foo: true}}).json();
console.log(json);
//=> `{data: '🦄'}`
Với fetch
thông thường, nó sẽ là:
class HTTPError extends Error {}
const response = await fetch('https://example.com', {
method: 'POST',
body: JSON.stringify({foo: true}),
headers: {
'content-type': 'application/json'
}
});
if (!response.ok) {
throw new HTTPError(`Fetch error: ${response.statusText}`);
}
const json = await response.json();
console.log(json);
//=> `{data: '🦄'}`
Nếu bạn đang sử dụng Deno, hãy nhập Ky từ một URL. Ví dụ, sử dụng CDN:
import ky from 'https://esm.sh/ky';
API
ky(input, options?)
Tham số input
và options
giống như fetch, với một số ngoại lệ:
- Tùy chọn
credentials
mặc định làsame-origin
, đây cũng là giá trị mặc định trong đặc tả, nhưng không phải tất cả các trình duyệt đã bắt kịp. - Thêm một số tùy chọn khác. Xem bên dưới.
Trả về một Response object với Body methods được thêm vào để tiện lợi. Vì vậy, bạn có thể gọi ky.get(input).json()
trực tiếp ví dụ mà không cần phải đợi Response
trước. Khi được gọi như vậy, một tiêu đề Accept
phù hợp sẽ được thiết lập dựa trên phương thức body được sử dụng. Khác với các phương thức Body
của window.Fetch
; những phương thức này sẽ ném một HTTPError
nếu trạng thái phản hồi không nằm trong phạm vi 200...299
. Ngoài ra, .json()
sẽ trả về một chuỗi trống nếu body là trống hoặc trạng thái phản hồi là 204
thay vì ném lỗi phân tích do body trống.
ky.get(input, options?)
ky.post(input, options?)
ky.put(input, options?)
ky.patch(input, options?)
ky.head(input, options?)
ky.delete(input, options?)
Đặt options.method
thành tên phương thức và thực hiện một yêu cầu.
Khi sử dụng một Request
instance như input
, bất kỳ tùy chọn biến đổi URL nào (như prefixUrl
) sẽ bị bỏ qua.
options
Loại: object
method
Loại: string
Mặc định: 'get'
Phương thức HTTP được sử dụng để thực hiện yêu cầu.
Một cách nội tại, các phương thức tiêu chuẩn (GET
, POST
, PUT
, PATCH
, HEAD
và DELETE
) được viết hoa để tránh lỗi máy chủ do sự nhạy cảm về kiểu chữ.
json
Loại: object
và bất kỳ giá trị nào được chấp nhận bởi JSON.stringify()
Là phím tắt để gửi JSON. Sử dụng điều này thay vì tùy chọn body
. Chấp nhận bất kỳ đối tượng hoặc giá trị nào, sẽ được JSON.stringify()
và gửi trong body với tiêu đề đúng.
searchParams
Loại: string | object<string, string | number | boolean> | Array<Array<string | number | boolean>> | URLSearchParams
Mặc định: ''
Tham số tìm kiếm để bao gồm trong URL yêu cầu. Đặt điều này sẽ ghi đè tất cả các tham số tìm kiếm hiện có trong URL đầu vào.
Chấp nhận bất kỳ giá trị nào được hỗ trợ bởi URLSearchParams().
prefixUrl
Loại: string | URL
Một tiền tố để đặt trước URL input
khi thực hiện yêu cầu. Nó có thể là bất kỳ URL hợp lệ nào, cả tương đối lẫn tuyệt đối. Dấu gạch chéo cuối /
là tùy chọn và sẽ được thêm tự động, nếu cần, khi nó được kết hợp với input
. Chỉ có hiệu lực khi input
là một chuỗi. Đối số input
không thể bắt đầu bằng dấu gạch chéo /
khi sử dụng tùy chọn này.
Hữu ích khi kết hợp với ky.extend() để tạo ra các phiên bản Ky riêng biệt dành cho các lĩnh vực cụ thể.
import ky from 'ky';
// On https://example.com
const response = await ky('unicorn', {prefixUrl: '/api'});
//=> 'https://example.com/api/unicorn'
const response2 = await ky('unicorn', {prefixUrl: 'https://cats.com'});
//=> 'https://cats.com/unicorn'
Lưu ý:
- Sau khi
prefixUrl
vàinput
được kết hợp, kết quả được giải quyết so với base URL của trang (nếu có). - Gạch chéo đầu tiên trong
input
bị cấm khi sử dụng tùy chọn này để đảm bảo tính nhất quán và tránh sự nhầm lẫn về cách URLinput
được xử lý, bởi vìinput
sẽ không tuân theo quy tắc giải quyết URL bình thường khiprefixUrl
được sử dụng, điều này thay đổi ý nghĩa của dấu gạch chéo đầu tiên.
retry
Loại: object | number
Mặc định:
limit
:2
methods
:get
put
head
delete
options
trace
statusCodes
: 408 413 429 500 502 503 504maxRetryAfter
:undefined
backoffLimit
:undefined
Một đối tượng đại diện cho các trường limit
, methods
, statusCodes
và maxRetryAfter
cho số lần thử lại tối đa, các phương thức được cho phép, các mã trạng thái được cho phép và thời gian Retry-After tối đa.
Nếu retry
là một số, nó sẽ được sử dụng làm limit
và các giá trị mặc định khác sẽ được giữ nguyên.
Nếu maxRetryAfter
được đặt thành undefined
, nó sẽ sử dụng options.timeout
. Nếu tiêu đề Retry-After lớn hơn maxRetryAfter
, nó sẽ hủy yêu cầu.
Tùy chọn backoffLimit
là giới hạn trên cùng của độ trễ mỗi lần thử lại tính bằng mili giây. Để giới hạn độ trễ, đặt backoffLimit
thành 1000, ví dụ. Mặc định, độ trễ được tính toán bằng công thức 0.3 * (2 ** (attemptCount - 1)) * 1000
. Độ trễ tăng theo cấp số mũ.
Không có thử lại sau một timeout.
import ky from 'ky';
const json = await ky('https://example.com', {
retry: {
limit: 10,
methods: ['get'],
statusCodes: [413],
backoffLimit: 3000
}
}).json();
timeout
Loại: number | false
Mặc định: 10000
Thời gian chờ tính bằng mili giây để nhận phản hồi, bao gồm bất kỳ lần thử lại nào. Không thể lớn hơn 2147483647. Nếu đặt thành false
, sẽ không có thời gian chờ.
hooks
Loại: object<string, Function[]>
Mặc định: {beforeRequest: [], beforeRetry: [], afterResponse: []}
Hooks cho phép thực hiện các sửa đổi trong vòng đời yêu cầu. Các hàm hook có thể là async và được thực hiện theo thứ tự.
hooks.beforeRequest
Loại: Function[]
Mặc định: []
Hook này cho phép bạn sửa đổi yêu cầu ngay trước khi nó được gửi. Ky sẽ không thay đổi yêu cầu thêm sau khi điều này xảy ra. Hàm hook nhận request
và options
làm đối số. Bạn có thể, ví dụ, sửa đổi request.headers
ở đây.
Hook có thể trả về một Request để thay thế yêu cầu ra ngoài, hoặc trả về một Response để hoàn toàn tránh việc thực hiện yêu cầu HTTP. Điều này có thể được sử dụng để giả lập một yêu cầu, kiểm tra bộ nhớ cache nội bộ, v.v. Quan trọng khi trả về một yêu cầu hoặc phản hồi từ hook này là bất kỳ hook beforeRequest
nào còn lại sẽ bị bỏ qua, vì vậy bạn có thể muốn chỉ trả về chúng từ hook cuối cùng.
import ky from 'ky';
const api = ky.extend({
hooks: {
beforeRequest: [
request => {
request.headers.set('X-Requested-With', 'ky');
}
]
}
});
const response = await api.get('https://example.com/api/users');
hooks.beforeRetry
Loại: Function[]
Mặc định: []
Hook này cho phép bạn sửa đổi yêu cầu ngay trước khi thử lại. Ky sẽ không thực hiện thêm bất kỳ sự thay đổi nào vào yêu cầu sau điều này. Hàm hook nhận một đối tượng với yêu cầu và tùy chọn được chuẩn hóa, một phiên bản lỗi và số lần thử lại. Bạn có thể, ví dụ, sửa đổi request.headers
ở đây.
Nếu yêu cầu nhận được một phản hồi, lỗi sẽ có kiểu HTTPError
và đối tượng Response
sẽ có sẵn tại error.response
. Hãy lưu ý rằng một số loại lỗi, như lỗi mạng, ngầm hiểu rằng không có phản hồi được nhận. Trong trường hợp đó, lỗi sẽ không phải là một phiên bản của HTTPError
.
Bạn có thể ngăn Ky thử lại yêu cầu bằng cách ném một lỗi. Ky sẽ không xử lý nó bằng bất kỳ cách nào và lỗi sẽ được truyền đến người gửi yêu cầu. Các hook beforeRetry
còn lại sẽ không được gọi trong trường hợp này. Hoặc bạn có thể trả về ký tự ky.stop để thực hiện điều tương tự nhưng không truyền lỗi (điều này có một số giới hạn, xem tài liệu ky.stop
để biết chi tiết).
import ky from 'ky';
const response = await ky('https://example.com', {
hooks: {
beforeRetry: [
async ({request, options, error, retryCount}) => {
const token = await ky('https://example.com/refresh-token');
request.headers.set('Authorization', `token ${token}`);
}
]
}
});
hooks.beforeError
Loại: Function[]
Mặc định: []
Hook này cho phép bạn sửa đổi HTTPError
ngay trước khi nó được ném ra. Hàm hook nhận một HTTPError
như một đối số và nên trả về một phiên bản của HTTPError
.
import ky from 'ky';
await ky('https://example.com', {
hooks: {
beforeError: [
error => {
const {response} = error;
if (response && response.body) {
error.name = 'GitHubError';
error.message = `${response.body.message} (${response.status})`;
}
return error;
}
]
}
});
hooks.afterResponse
Loại: Function[]
Mặc định: []
Hook này cho phép bạn đọc và tùy chọn sửa đổi phản hồi. Hàm hook nhận yêu cầu được chuẩn hóa, tùy chọn và một bản sao của phản hồi như đối số. Giá trị trả về của hàm hook sẽ được Ky sử dụng như đối tượng phản hồi nếu nó là một phiên bản của Response.
import ky from 'ky';
const response = await ky('https://example.com', {
hooks: {
afterResponse: [
(_request, _options, response) => {
// You could do something with the response, for example, logging.
log(response);
// Or return a `Response` instance to overwrite the response.
return new Response('A different response', {status: 200});
},
// Or retry with a fresh token on a 403 error
async (request, options, response) => {
if (response.status === 403) {
// Get a fresh token
const token = await ky('https://example.com/token').text();
// Retry with the token
request.headers.set('Authorization', `token ${token}`);
return ky(request);
}
}
]
}
});
throwHttpErrors
Loại: boolean
Mặc định: true
Ném một HTTPError
khi, sau khi theo dõi các chuyển hướng, phản hồi có mã trạng thái không phải là 2xx. Để cũng ném lỗi cho các chuyển hướng thay vì theo dõi chúng, đặt tùy chọn redirect thành 'manual'
.
Đặt thành false
có thể hữu ích nếu bạn kiểm tra tính khả dụng của tài nguyên và mong đợi các phản hồi lỗi.
Lưu ý: Nếu đặt thành false
, các phản hồi lỗi được xem xét là thành công và yêu cầu sẽ không được thử lại.
onDownloadProgress
Loại: Function
Xử lý sự kiện tiến trình tải về.
Hàm nhận một đối số progress
và chunk
:
- Đối tượng
progress
chứa các phần tử sau:percent
,transferredBytes
vàtotalBytes
. Nếu không thể truy xuất kích thước thân,totalBytes
sẽ là0
. -
Đối số
chunk
là một phiên bản củaUint8Array
. Nó rỗng cho lần gọi đầu tiên.import ky from ‘ky’;
const response = await ky(‘https://example.com’, {
onDownloadProgress: (progress, chunk) => {
// Example output:
//0% - 0 of 1271 bytes
//100% - 1271 of 1271 bytes
console.log(${progress.percent * 100}% - ${progress.transferredBytes} of ${progress.totalBytes} bytes
);
}
});
parseJson
Loại: Function
Mặc định: JSON.parse()
Hàm phân tích JSON do người dùng định nghĩa.
Các trường hợp sử dụng:
. Phân tích JSON thông qua bourne package để bảo vệ khỏi ô nhiễm prototype.
. Phân tích JSON với reviver option of JSON.parse().
import ky from 'ky';
import bourne from '@hapijs/bourne';
const json = await ky('https://example.com', {
parseJson: text => bourne(text)
}).json();
fetch
Loại: Function
Mặc định: fetch
Hàm fetch
do người dùng định nghĩa. Phải hoàn toàn tương thích với tiêu chuẩn Fetch API.
Các trường hợp sử dụng:
. Sử dụng các triển khai fetch
tùy chỉnh như isomorphic-unfetch.
. Sử dụng hàm bọc fetch
được cung cấp bởi một số framework sử dụng server-side rendering (SSR).
import ky from 'ky';
import fetch from 'isomorphic-unfetch';
const json = await ky('https://example.com', {fetch}).json();
ky.extend(defaultOptions)
Tạo một phiên bản ky
mới với một số giá trị mặc định được ghi đè bằng giá trị của bạn.
Khác với ky.create()
, ky.extend()
kế thừa các giá trị mặc định từ cha của nó.
Bạn có thể truyền tiêu đề dưới dạng một phiên bản Headers
hoặc một đối tượng thường.
Bạn có thể loại bỏ một tiêu đề bằng cách sử dụng .extend()
và truyền tiêu đề với giá trị undefined
. Truyền undefined
dưới dạng chuỗi sẽ loại bỏ tiêu đề chỉ khi nó xuất phát từ một trường hợp Headers
.
import ky from 'ky';
const url = 'https://sindresorhus.com';
const original = ky.create({
headers: {
rainbow: 'rainbow',
unicorn: 'unicorn'
}
});
const extended = original.extend({
headers: {
rainbow: undefined
}
});
const response = await extended(url).json();
console.log('rainbow' in response);
//=> false
console.log('unicorn' in response);
//=> true
ky.create(defaultOptions)
Tạo một phiên bản Ky mới với các thiết lập mặc định hoàn toàn mới.
import ky from 'ky';
// On https://my-site.com
const api = ky.create({prefixUrl: 'https://example.com/api'});
const response = await api.get('users/123');
//=> 'https://example.com/api/users/123'
const response = await api.get('/status', {prefixUrl: ''});
//=> 'https://my-site.com/status'
defaultOptions
Loại: object
ky.stop
Một Symbol
có thể được trả về bởi một hook beforeRetry
để dừng việc thử lại. Điều này cũng sẽ ngắt kết nối ngắn mạch các hook beforeRetry
còn lại.
Lưu ý: Trả về biểu tượng này khiến Ky ngừng và trả về với một phản hồi undefined
. Hãy chắc chắn kiểm tra phản hồi trước khi truy cập bất kỳ thuộc tính nào trên nó hoặc sử dụng optional chaining. Nó cũng không tương thích với các phương thức body như .json()
hoặc .text()
vì không có phản hồi để phân tích. Nói chung, chúng tôi khuyên bạn ném một lỗi thay vì trả về biểu tượng này, vì điều đó sẽ làm Ky dừng lại và sau đó ném, tránh những hạn chế này.
Một tình huống sử dụng hợp lệ cho ky.stop
là ngăn chặn việc thử lại khi thực hiện các yêu cầu để tạo ra hiệu ứng phụ, nơi dữ liệu trả về không quan trọng. Ví dụ, ghi hoạt động của máy khách vào máy chủ.
import ky from 'ky';
const options = {
hooks: {
beforeRetry: [
async ({request, options, error, retryCount}) => {
const shouldStopRetry = await ky('https://example.com/api');
if (shouldStopRetry) {
return ky.stop;
}
}
]
}
};
// Note that response will be `undefined` in case `ky.stop` is returned.
const response = await ky.post('https://example.com', options);
// Using `.text()` or other body methods is not supported.
const text = await ky('https://example.com', options).text();
HTTPError
Tiếp cận cho các kiểm tra instanceof
. Lỗi có một thuộc tính response
với Response object, thuộc tính request
với Request object, và thuộc tính options
với các tùy chọn được chuẩn hóa (hoặc được truyền cho ky
khi tạo một phiên bản với ky.create()
hoặc trực tiếp khi thực hiện yêu cầu).
Nếu bạn cần đọc phản hồi thực tế khi có một HTTPError
, hãy gọi phương thức phân tích cú pháp tương ứng trên đối tượng phản hồi. Ví dụ:
try {
await ky('https://example.com').json();
} catch (error) {
if (error.name === 'HTTPError') {
const errorJson = await error.response.json();
}
}
TimeoutError
Lỗi được ném khi yêu cầu vượt quá thời gian chờ. Nó có một thuộc tính request
với Request object.
Gợi ý
Gửi dữ liệu biểu mẫu
Gửi dữ liệu biểu mẫu trong Ky hoàn toàn giống với fetch
. Chỉ cần truyền một thể hiện của FormData vào tùy chọn body
. Tiêu đề Content-Type
sẽ tự động được đặt thành multipart/form-data
.
import ky from 'ky';
// `multipart/form-data`
const formData = new FormData();
formData.append('food', 'fries');
formData.append('drink', 'icetea');
const response = await ky.post(url, {body: formData});
Nếu bạn muốn gửi dữ liệu theo định dạng application/x-www-form-urlencoded
, bạn sẽ cần mã hóa dữ liệu bằng URLSearchParams.
import ky from 'ky';
// `application/x-www-form-urlencoded`
const searchParams = new URLSearchParams();
searchParams.set('food', 'fries');
searchParams.set('drink', 'icetea');
const response = await ky.post(url, {body: searchParams});
Đặt một Content-Type
tùy chỉnh
Ky tự động đặt một tiêu đề Content-Type phù hợp cho mỗi yêu cầu dựa trên dữ liệu trong phần thân yêu cầu. Tuy nhiên, một số API yêu cầu các loại nội dung tùy chỉnh, không tiêu chuẩn, như application/x-amz-json-1.1
. Bằng cách sử dụng tùy chọn headers
, bạn có thể ghi đè thủ công trên loại nội dung.
import ky from 'ky';
const json = await ky.post('https://example.com', {
headers: {
'content-type': 'application/json'
},
json: {
foo: true
},
}).json();
console.log(json);
//=> `{data: '🦄'}`
Hủy bỏ
Fetch (và do đó Ky) tích hợp sẵn hỗ trợ hủy bỏ yêu cầu thông qua AbortController API. Read more.
Ví dụ:
import ky from 'ky';
const controller = new AbortController();
const {signal} = controller;
setTimeout(() => {
controller.abort();
}, 5000);
try {
console.log(await ky(url, {signal}).text());
} catch (error) {
if (error.name === 'AbortError') {
console.log('Fetch aborted');
} else {
console.error('Fetch error:', error);
}
}
Câu hỏi thường gặp
Làm thế nào để sử dụng điều này trong Node.js?
Hãy xem ky-universal.
Làm thế nào để sử dụng điều này với ứng dụng web (React, Vue.js, vv.) sử dụng việc tạo nội dung phía máy chủ (SSR)?
Hãy xem ky-universal.
Làm thế nào để kiểm tra một thư viện trình duyệt sử dụng điều này?
Hoặc sử dụng một công cụ chạy kiểm tra có thể chạy trong trình duyệt, như Mocha, hoặc sử dụng AVA với ky-universal
. Read more.
Làm thế nào để sử dụng điều này mà không cần một công cụ đóng gói như Webpack?
Hãy đảm bảo mã của bạn đang chạy như một mô-đun JavaScript (ESM), ví dụ bằng cách sử dụng một thẻ <script type="module">
trong tài liệu HTML của bạn. Sau đó, Ky có thể được nhập trực tiếp bởi mô-đun đó mà không cần công cụ đóng gói hoặc các công cụ khác.
<script type="module">
import ky from 'https://unpkg.com/ky/distribution/index.js';
const json = await ky('https://jsonplaceholder.typicode.com/todos/1').json();
console.log(json.title);
//=> 'delectus aut autem
</script>
Nó khác biệt như thế nào so với got
Xem câu trả lời của tôi tại here. Got được duy trì bởi cùng một nhóm người như Ky.
Nó khác biệt như thế nào so với axios?
Xem câu trả lời của tôi tại here.
Nó khác biệt như thế nào so với r2?
Xem câu trả lời của tôi tại #10.
ky
có nghĩa là gì?
Đó chỉ là một tên gói npm ngắn ngọn ngẫu nhiên mà tôi đã quản lý được. Tuy nhiên, nó có nghĩa trong tiếng Nhật:
Là một hình thức lóng le lời nói qua tin nhắn, KY là viết tắt của 空気読めない (kuuki yomenai), có nghĩa đen là “không thể đọc được bầu không khí.” Đó là một cụm từ áp dụng cho người nào bỏ lỡ ý nghĩa tiềm ẩn.
Hỗ trợ trình duyệt
Phiên bản mới nhất của Chrome, Firefox và Safari.
Hỗ trợ Node.js
Bổ sung các biến toàn cục trình duyệt cần thiết hoặc chỉ cần sử dụng ky-universal.
Liên quan
- ky-universal – Sử dụng Ky trên cả Node.js và trình duyệt
- got – Yêu cầu HTTP đơn giản cho Node.js
- ky-hooks-change-case – Các hook Ky để sửa đổi các trường hợp trên yêu cầu và phản hồi của các đối tượng
Người duy trì
Chi tiết Tải xuống:
Tác giả: Sindresorhus
Mã nguồn: https://github.com/sindresorhus/ky
Giấy phép: MIT license