Use cancellation when a request is no longer needed, or when an extended client needs a different cancellation lifetime. Ky builds on Fetch: pass an AbortController's signal through the signal option, then call abort() to cancel.
1. Pass a signal and handle cancellation
This sample runs in a browser or Node.js with Fetch support. It follows the authors' cancellation example: start a request, cancel it with a timer, and distinguish cancellation from other failures. Use a slow endpoint so the request is still pending when the timer fires.
tsimport ky from 'ky';
async function main() {
const controller = new AbortController();
const timer = setTimeout(() => {
controller.abort();
}, 500);
try {
const text = await ky.get('https://httpbin.org/delay/2', {
signal: controller.signal,
}).text();
console.log(text);
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
console.log('Fetch aborted');
} else {
console.error('Fetch error:', error);
}
} finally {
clearTimeout(timer);
}
}
void main();
With a pending request, abort() makes the awaited operation reject with an error named AbortError, and the cancellation branch prints Fetch aborted. If the request finishes first, .text() returns the response body as a string instead. Keep other failures in a separate branch rather than treating every rejection as cancellation.
2. Replace an inherited signal
By default, extend() combines inherited and new signals: either controller can cancel the extended client's requests. Use replaceOption when only the new controller must control the child client.
tsimport ky, {replaceOption} from 'ky';
async function main() {
const parentController = new AbortController();
const replacementController = new AbortController();
const api = ky.create({signal: parentController.signal});
const childApi = api.extend({
signal: replaceOption(replacementController.signal),
});
parentController.abort();
try {
const text = await childApi.get('https://httpbin.org/get').text();
console.log(text);
} catch (error) {
console.error('Fetch error:', error);
}
const pending = childApi.get('https://httpbin.org/delay/2').text();
replacementController.abort();
try {
await pending;
} catch (error) {
if (error instanceof Error && error.name === 'AbortError') {
console.log('Child request aborted');
} else {
console.error('Fetch error:', error);
}
}
}
void main();
Aborting the parent does not cancel the child's first request. Look for your endpoint's response text. The replacement controller cancels the subsequent child request. extend() returns a new client; the parent retains its original defaults.
3. Remove an inherited signal
Pass signal: undefined to extend() to remove inherited signals without installing a replacement. The child can make requests even after the parent controller is aborted.
tsimport ky from 'ky';
async function main() {
const parentController = new AbortController();
const api = ky.create({signal: parentController.signal});
const independentApi = api.extend({signal: undefined});
parentController.abort();
try {
const text = await independentApi.get('https://httpbin.org/get').text();
console.log(text);
} catch (error) {
console.error('Fetch error:', error);
}
}
void main();
The parent signal no longer cancels this request. You can still pass a fresh signal in an individual request's options to make that request cancellable.
Options and pitfalls
The cancellation option belongs to Options.
| Option | Type | Default | What it does |
|---|---|---|---|
signal | AbortSignal | null | undefined | Not set | Supplies a Fetch cancellation signal. In extend(), a new signal combines with inherited signals; replaceOption(signal) replaces them, and explicit undefined removes them. |
- Create a fresh controller for a new cancellation lifetime. A request using an already-aborted signal rejects rather than starting a fresh operation.
- Signal combination requires
AbortSignal.any(). Without it, Ky uses the last supplied signal instead of combining signals. - The
AbortErrorcheck above applies toabort()without a custom reason. If you pass a reason toabort(reason), handle that reason: Ky surfaces the user signal's abort reason.
Related
- Instances and defaults explains how to compose client defaults.
- Handle request errors covers failures other than cancellation.
- Retry failed requests covers retry policy and timeouts.
Was this page helpful?