Ky是一个基于Fetch API的小巧而优雅的HTTP客户端
Ky针对现代浏览器、Node.js、Bun和Deno。
它只是一个没有依赖项的小型包。
fetch
的优势ky.post()
).json()
支持泛型并默认为unknown
,而不是any
)npm install ky
import ky from 'ky'; const json = await ky.post('https://example.com', {json: {foo: true}}).json(); console.log(json); //=> `{data: '🦄'}`
使用普通的fetch
,它将是:
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: '🦄'}`
如果你使用的是Deno,从URL导入Ky。例如,使用CDN:
import ky from 'https://esm.sh/ky';
input
和options
与fetch
相同,还提供了额外的options
(见下文)。
返回一个带有Body
方法的Response
对象,以方便使用。因此,你可以直接调用ky.get(input).json()
,而不必先等待Response
。当这样调用时,将根据使用的body方法设置适当的Accept
头。与window.Fetch
的Body
方法不同,如果响应状态不在200...299
范围内,这些方法将抛出HTTPError
。此外,如果body为空或响应状态为204
,.json()
将返回空字符串,而不是因为空body而抛出解析错误。
import ky from 'ky'; const user = await ky('/api/user').json(); console.log(user);
⌨️ TypeScript: 接受一个可选的类型参数,默认为unknown
,并传递给.json()
的返回类型。
import ky from 'ky'; // user1是unknown类型 const user1 = await ky('/api/users/1').json(); // user2是User类型 const user2 = await ky<User>('/api/users/2').json(); // user3是User类型 const user3 = await ky('/api/users/3').json<User>(); console.log([user1, user2, user3]);
将options.method
设置为方法名并发起请求。
⌨️ TypeScript: 接受一个可选的类型参数,用于JSON响应(参见ky()
)。
类型:string
| URL
| Request
与fetch
input相同。
当使用Request
实例作为input
时,任何改变URL的选项(如prefixUrl
)将被忽略。
类型:object
与fetch
options相同,外加以下额外选项:
类型:string
默认值:'get'
用于发起请求的HTTP方法。
内部会将标准方法(GET
、POST
、PUT
、PATCH
、HEAD
和DELETE
)转为大写,以避免由于大小写敏感性导致的服务器错误。
类型:object
和JSON.stringify()
接受的任何其他值
发送JSON的快捷方式。使用此选项代替body
选项。接受任何普通对象或值,这些值将被JSON.stringify()
处理并在正文中发送,同时设置正确的头部。
类型:string | object<string, string | number | boolean> | Array<Array<string | number | boolean>> | URLSearchParams
默认值:''
要包含在请求URL中的搜索参数。设置此项将覆盖输入URL中的所有现有搜索参数。
接受URLSearchParams()
支持的任何值。
类型:string | URL
在发起请求时,要预先添加到input
URL的前缀。它可以是任何有效的URL,相对或绝对。末尾的斜杠/
是可选的,如果需要,在与input
连接时会自动添加。仅当input
是字符串时生效。使用此选项时,input
参数不能以斜杠/
开头。
在使用ky.extend()
创建特定领域的Ky实例时非常有用。
import ky from 'ky'; // 在 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'
注意:
prefixUrl
和 input
后,结果会根据页面的基础 URL(如果有)进行解析。input
中有前导斜杠,以确保一致性并避免对 input
URL 处理方式产生混淆。因为使用 prefixUrl
时,input
不会遵循正常的 URL 解析规则,这改变了前导斜杠的含义。类型:object | number
默认值:
limit
:2
methods
:get
put
head
delete
options
trace
statusCodes
:408
413
429
500
502
503
504
afterStatusCodes
:413
、429
、503
maxRetryAfter
:undefined
backoffLimit
:undefined
delay
:attemptCount => 0.3 * (2 ** (attemptCount - 1)) * 1000
一个对象,表示最大重试次数、允许的方法、允许的状态码、允许使用 Retry-After
时间的状态码,以及最大 Retry-After
时间的 limit
、methods
、statusCodes
、afterStatusCodes
和 maxRetryAfter
字段。
如果 retry
是一个数字,它将被用作 limit
,其他默认值保持不变。
如果响应提供的 HTTP 状态包含在 afterStatusCodes
中,Ky 将等待 Retry-After
头部给出的日期、超时或时间戳过去后再重试请求。如果缺少 Retry-After
,则使用非标准的 RateLimit-Reset
头部作为备用。如果提供的状态码不在列表中,将忽略 Retry-After
头部。
如果 maxRetryAfter
设置为 undefined
,它将使用 options.timeout
。如果 Retry-After
头部大于 maxRetryAfter
,它将使用 maxRetryAfter
。
backoffLimit
选项是每次重试延迟的上限(以毫秒为单位)。
要限制延迟,可以将 backoffLimit
设置为 1000,例如。
默认情况下,延迟使用 0.3 * (2 ** (attemptCount - 1)) * 1000
计算。延迟呈指数增长。
delay
选项可用于更改计算重试之间延迟的方式。该函数接收一个参数,即尝试次数,从 1
开始。
超时后不会触发重试。
import ky from 'ky'; const json = await ky('https://example.com', { retry: { limit: 10, methods: ['get'], statusCodes: [413], backoffLimit: 3000 } }).json();
类型:number | false
默认值:10000
获取响应的超时时间(毫秒),包括任何重试。不能大于 2147483647。
如果设置为 false
,则不会有超时。
类型:object<string, Function[]>
默认值:{beforeRequest: [], beforeRetry: [], afterResponse: []}
钩子允许在请求生命周期中进行修改。钩子函数可以是异步的,并且按顺序运行。
类型:Function[]
默认值:[]
此钩子使您能够在请求发送之前修改请求。在此之后,Ky 不会对请求做任何进一步的更改。钩子函数接收 request
和 options
作为参数。例如,您可以在这里修改 request.headers
。
钩子可以返回一个 Request
来替换即将发出的请求,或返回一个 Response
来完全避免发出 HTTP 请求。这可以用于模拟请求、检查内部缓存等。从此钩子返回请求或响应时的一个重要考虑因素是,任何剩余的 beforeRequest
钩子将被跳过,因此您可能只想从最后一个钩子返回它们。
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');
类型:Function[]
默认值:[]
此钩子使您能够在重试之前修改请求。在此之后,Ky 不会对请求做任何进一步的更改。钩子函数接收一个包含规范化的请求和选项、错误实例以及重试次数的对象。例如,您可以在这里修改 request.headers
。
如果请求收到响应,错误将是 HTTPError
类型,并且 Response
对象将在 error.response
中可用。请注意,某些类型的错误(如网络错误)本质上意味着没有收到响应。在这种情况下,错误将不是 HTTPError
的实例。
您可以通过抛出错误来阻止 Ky 重试请求。Ky 不会以任何方式处理它,错误将传播给请求发起者。在这种情况下,剩余的 beforeRetry
钩子将不会被调用。或者,您可以返回 ky.stop
符号来做同样的事情,但不传播错误(这有一些限制,详见 ky.stop
文档)。
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}`); } ] } });
类型:Function[]
默认值:[]
此钩子使您能够在抛出 HTTPError
之前修改它。钩子函数接收一个 HTTPError
作为参数,并应返回一个 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; } ] } });
类型:Function[]
默认值:[]
此钩子使您能够读取和可选地修改响应。钩子函数接收规范化的请求、选项和响应的克隆作为参数。如果钩子函数的返回值是 Response
的实例,Ky 将使用它作为响应对象。
import ky from 'ky'; const response = await ky('https://example.com', { hooks: { afterResponse: [ (_request, _options, response) => { // 你可以对响应做一些处理,比如记录日志 log(response); // 或者返回一个新的 Response 实例来覆盖原响应 return new Response('一个不同的响应', {status: 200}); }, // 或者在遇到 403 错误时使用新的 token 重试 async (request, options, response) => { if (response.status === 403) { // 获取新的 token const token = await ky('https://example.com/token').text(); // 使用新 token 重试 request.headers.set('Authorization', `token ${token}`); return ky(request); } } ] } });
类型: boolean
默认值: true
当响应状态码非 2xx 时(在跟随重定向之后),抛出 HTTPError
。如果要对重定向也抛出错误而不是跟随它们,请将 redirect
选项设置为 'manual'
。
将此选项设置为 false
可能在检查资源可用性并期望出现错误响应时有用。
注意:如果设为 false
,错误响应将被视为成功,请求不会重试。
类型: Function
下载进度事件处理函数。
该函数接收 progress
和 chunk
参数:
progress
对象包含以下元素:percent
、transferredBytes
和 totalBytes
。如果无法获取主体大小,totalBytes
将为 0
。chunk
参数是 Uint8Array
的实例。第一次调用时为空。import ky from 'ky'; const response = await ky('https://example.com', { onDownloadProgress: (progress, chunk) => { // 示例输出: // `0% - 0 of 1271 bytes` // `100% - 1271 of 1271 bytes` console.log(`${progress.percent * 100}% - ${progress.transferredBytes} of ${progress.totalBytes} bytes`); } });
类型: Function
默认值: JSON.parse()
用户自定义 JSON 解析函数。
使用场景:
bourne
包 解析 JSON 以防止原型污染。JSON.parse()
的 reviver
选项 解析 JSON。import ky from 'ky'; import bourne from '@hapijs/bourne'; const json = await ky('https://example.com', { parseJson: text => bourne(text) }).json();
类型: Function
默认值: JSON.stringify()
用户自定义 JSON 字符串化函数。
使用场景:
replacer
函数字符串化 JSON。import ky from 'ky'; import {DateTime} from 'luxon'; const json = await ky('https://example.com', { stringifyJson: data => JSON.stringify(data, (key, value) => { if (key.endsWith('_at')) { return DateTime.fromISO(value).toSeconds(); } return value; }) }).json();
类型: Function
默认值: fetch
用户自定义 fetch
函数。
必须完全兼容 Fetch API 标准。
使用场景:
fetch
实现,如 isomorphic-unfetch
。fetch
包装函数。import ky from 'ky'; import fetch from 'isomorphic-unfetch'; const json = await ky('https://example.com', {fetch}).json();
创建一个新的 ky
实例,覆盖一些默认选项。
与 ky.create()
不同,ky.extend()
会继承其父实例的默认值。
你可以将 headers 作为 Headers
实例或普通对象传递。
你可以通过传递值为 undefined
的 header 来删除 header。
作为字符串传递 undefined
只有在 header 来自 Headers
实例时才会删除该 header。
类似地,你可以通过显式传递 undefined
来删除现有的 hooks
条目。
import ky from 'ky'; const url = 'https://sindresorhus.com'; const original = ky.create({ headers: { rainbow: 'rainbow', unicorn: 'unicorn' }, hooks: { beforeRequest: [ () => console.log('before 1') ], afterResponse: [ () => console.log('after 1') ], }, }); const extended = original.extend({ headers: { rainbow: undefined }, hooks: { beforeRequest: undefined, afterResponse: [ () => console.log('after 2') ], } }); const response = await extended(url).json(); //=> after 1 //=> after 2 console.log('rainbow' in response); //=> false console.log('unicorn' in response); //=> true
你也可以通过向 .extend()
提供函数来引用父实例的默认值。
import ky from 'ky'; const api = ky.create({prefixUrl: 'https://example.com/api'}); const usersApi = api.extend((options) => ({prefixUrl: `${options.prefixUrl}/users`})); const response = await usersApi.get('123'); //=> 'https://example.com/api/users/123' const response = await api.get('version'); //=> 'https://example.com/api/version'
创建一个具有全新默认值的 Ky 实例。
import ky from 'ky'; // 在 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'
类型: object
一个可以由 beforeRetry
钩子返回以停止重试的 Symbol
。这也会短路剩余的 beforeRetry
钩子。
注意:返回此符号会使 Ky 中止并返回 undefined
响应。在访问响应的任何属性之前,请确保检查响应是否存在,或使用可选链。它也与 .json()
或 .text()
等主体方法不兼容,因为没有响应可供解析。一般来说,我们建议抛出错误而不是返回此符号,因为这会导致 Ky 中止然后抛出,从而避免这些限制。
ky.stop
的一个有效用例是在进行副作用请求时防止重试,这种情况下返回的数据并不重要。例如,向服务器记录客户端活动。
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; } } ] } }; // 注意,如果返回 ky.stop,response 将为 `undefined`。 const response = await ky.post('https://example.com', options); // 不支持使用 `.text()` 或其他主体方法。 const text = await ky('https://example.com', options).text();
暴露用于 instanceof
检查。错误对象具有 response
属性(包含 Response
对象),request
属性(包含 Request
对象),以及 options
属性(包含规范化的选项,这些选项可能是在使用 ky.create()
创建实例时传递给 ky
的,或者是直接在执行请求时传递的)。
如果在发生 HTTPError
时需要读取实际响应,请在响应对象上调用相应的解析器方法。例如:
try { await ky('https://example.com').json(); } catch (error) { if (error.name === 'HTTPError') { const errorJson = await error.response.json(); } }
⌨️ TypeScript: 接受一个可选的类型参数,默认为unknown
,并传递给error.response.json()
的返回类型。
请求超时时抛出的错误。它有一个request
属性,包含Request
对象。
在Ky中发送表单数据与fetch
相同。只需将FormData
实例传递给body
选项。Content-Type
头部将自动设置为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});
如果你想以application/x-www-form-urlencoded
格式发送数据,你需要使用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});
Content-Type
Ky会根据请求体中的数据自动为每个请求设置适当的Content-Type
头部。但是,有些API需要自定义的非标准内容类型,如application/x-amz-json-1.1
。使用headers
选项,你可以手动覆盖内容类型。
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: '🦄'}`
Fetch(因此也包括Ky)通过AbortController
API内置支持请求取消。了解更多。
示例:
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); } }
Node.js 18及更高版本原生支持fetch
,所以你可以直接使用这个包。
与上述相同。
要么使用可以在浏览器中运行的测试运行器,如Mocha,要么使用AVA和ky-universal
。了解更多。
确保你的代码作为JavaScript模块(ESM)运行,例如在HTML文档中使用<script type="module">
标签。然后Ky可以直接被该模块导入,无需打包工具或其他工具。
<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>
got
有何不同?请参阅我的回答这里。Got由与Ky相同的人维护。
axios
有何不同?请参阅我的回答这里。
r2
有何不同?请参阅我在#10中的回答。
ky
是什么意思?这只是我设法获得的一个随机短npm包名。不过,它在日语中确实有意义:
一种可发短信的俚语,KY是空気読めない(kuuki yomenai)的缩写,字面意思是"无法读懂空气"。这个短语用于形容一个人无法理解暗示的含义。
最新版本的Chrome、Firefox和Safari。
Node.js 18及更高版本。
全能AI智能助手,随时解答生活与工作的多样问题
问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。
实时语音翻译/同声传译工具
Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。
一键生成PPT和Word,让学习生活更轻松
讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。
深度推理能力全新升级,全面对标OpenAI o1
科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。
一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型
Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。
字节跳动发布的AI编程神器IDE
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。
AI助力,做PPT更简单!
咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。
选题、配图、成文,一站式创作,让内容运营更高效
讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。
专业的AI公文写作平台,公文写作神器
AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。
OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。
openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。
最新AI工具、AI资讯
独家AI资源、AI项目落地
微信扫一扫关注公众号