Skip to content

Cancelling fetch request to SvelteKit API route with AbortSignal: timeout() does not work #13874

Closed
@eurlexa

Description

@eurlexa

Describe the bug

Trying to use standard AbortSignal: timeout() method: My use-case is to abort internal SvelteKit api route call if server process takes too long to finish. In that case I do the proces client side.

But SvelteKit does not abort the fetch call to its own api route for some reason.

My only workaround was to have a separate second SvelteKit application with the API in matter. Which is quite a hassle.

Reproduction

// routes/+page.svelte
Go to <a href="/roll">roll</a>
// routes/roll/+page.svelte
<script>
	let { data } = $props();
</script>

{data.number}
// routes/roll/+page.server.js
export const load = async ({fetch}) => {
    try {
        let response = await fetch(
            'api/longServerProcess'  // internal api call will not be aborted
            // "http://www.randomnumberapi.com/api/v1.0/randomnumber" //external api call will be aborted as expeted
            , {
        method: 'GET',
        signal: AbortSignal.timeout(100),
        headers: {
            'Content-Type': 'application/json',
        }
    });


    let number = await response.json()
    return {number}
} catch (error) {
     return {
        serverTooSlow: true,
        number: "api call interrupted cos server was too slow"
     }
}
}
// api/longServerProcess/+server.js
import { json } from '@sveltejs/kit';

const asyncTimeout = (ms) => {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
};

export async function GET() {
    await  asyncTimeout(5000)
    const number = Math.floor(Math.random() * 100) + 1;
	return json(number);
}

Not using SvelteKit fetch but the native one will cause AbortSignal.timeout(...) to abort internal api calls but wont respect the timeout value. The calls are aborted immediately.

export const load = async () => {
    try {
        let response = await fetch(
            'api/longServerProcess'  // is aborted immediately instead of after 10000 ms
            // "http://www.randomnumberapi.com/api/v1.0/randomnumber" // works as expected
            , {
        method: 'GET',
        signal: AbortSignal.timeout(10000), // time does not work, the abortion fires immediately 
        headers: {
            'Content-Type': 'application/json',
        }
    });


    let number = await response.json()
    return {number}
} catch (error) {
     return {
        serverTooSlow: true,
        number: "api call interrupted cos server was too slow"
     }
}
}

Logs

System Info

System:
    OS: Linux 6.12 Pop!_OS 22.04 LTS
    CPU: (4) x64 Intel(R) Pentium(R) CPU 3825U @ 1.90GHz
    Memory: 627.66 MB / 3.74 GB
    Container: Yes
    Shell: 5.1.16 - /bin/bash
  Binaries:
    Node: 20.10.0 - ~/.nvm/versions/node/v20.10.0/bin/node
    npm: 10.2.3 - ~/.nvm/versions/node/v20.10.0/bin/npm
    pnpm: 7.5.2 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/adapter-auto: ^6.0.0 => 6.0.1 
    @sveltejs/kit: ^2.16.0 => 2.21.1 
    @sveltejs/vite-plugin-svelte: ^5.0.0 => 5.0.3 
    svelte: ^5.0.0 => 5.33.13 
    vite: ^6.2.6 => 6.3.5

Severity

annoyance

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions