admin管理员组文章数量:1401199
The way I have it set up is a class that handles all the api calls. In this class I keep a map for GET requests, key is url, value is AbortController.
If a request is being sent and another one of the same type comes before the other has finished, then I call abort() on the prev one and honor the new one.
Problem is that I get many uncaught exceptions on svelte effects when signal is aborted, and adding try/catch everywhere would be a lot of hassle.
Are there better ay to handle this? In React there is reactquery, but I prefer not to use some external library if possible
The way I have it set up is a class that handles all the api calls. In this class I keep a map for GET requests, key is url, value is AbortController.
If a request is being sent and another one of the same type comes before the other has finished, then I call abort() on the prev one and honor the new one.
Problem is that I get many uncaught exceptions on svelte effects when signal is aborted, and adding try/catch everywhere would be a lot of hassle.
Are there better ay to handle this? In React there is reactquery, but I prefer not to use some external library if possible
Share Improve this question asked Mar 24 at 23:13 AlexAlex 66.1k185 gold badges459 silver badges651 bronze badges 1 |3 Answers
Reset to default 0You probably will have to handle each case properly. If you return some unexpected data in the abortion case, the code using it will also likely throw an exception.
So either add try
/catch
everywhere, or use the errors as values pattern, which I would recommend, since it encourages proper error handling.
In JS you can e.g. return an object with a status
property so you get various shapes of objects, depending on what happened, e.g.
{ status: 'ok', data: { /* ... */ } }
{ status: 'aborted' }
{ status: 'network-error', error: /* Error instance */ }
{ status: 'server-error', code: 500 }
In TypeScript these can be typed via a discriminated union, so if you check for a specific status, the flow analysis will recognize what properties exist on the object in that branch.
In you API code you would handle a rejection of the fetch and check the error name
for the value 'AbortError'
, in that case you resolve the request with the value { status: 'aborted' }
.
I don't know if this will work for you in practice, and even if it does it might be a bad idea, but you can in $effect()
use thePromise.then()
instead of await thePromise
. Then $effect()
will never complain about an uncaught exception from the promise.
However, if no one is listening for when the promise gets rejected, then the web browser will complain when it gets rejected, and you will still end up with a warning in the console (although not from $effect()
). But this one you can avoid by adding .catch()
callback to the promise (when you create it, or just before it will get rejected) that do nothing (like () => null
).
To answer your question: Svelte doesn't provision anything that could help you deal with the exceptions thrown by aborting an HTTP request for your particular case of discarding a previous, unfinished HTTP request in favor of a new one, and I don't see this happening as Svelte is a general-purpose, unopinionated UI framework.
The solution I propose is using my very new fetch wrapper: dr-fetch
Using dr-fetch
This question made me add support for auto-abortable HTTP requests, which is now available in v0.9.0.
Follow the package's quickstart to understand how to set a fetcher object up, then make an abortable fetcher out of the root (base) fetcher. Some code starting at this point:
// root-fetchers.ts
import { DrFetch } from "dr-fetch";
export const rootFetcher = new DrFetch(...); // Etc. Follow the README.
// Now the abortable fetcher.
export const abortableRootFetcher = rootFetcher.clone().abortable();
That's all you need to do to set the fetcher up. Just use it.
<!-- Autocomplete.svelte -->
<script lang="ts">
import { abortableRootFetcher } from './root-fetchers.js';
import type { AutoCompleteItem } from './my-types.js';
const searchKey = Symbol(); // A symbol is best for an autocomplete component.
let listItems = $state<AutoCompleteItem[]>([]);
async function search(searchTerm: string) {
const response = await abortableRootFetcher
.for<200, AutoCompleteItem[]>()
.for<204, undefined>()
.get(`/my/url?s=${searchTerm}`, { autoAbort: { key: searchKey, delay: 500 }});
if (!response.aborted) {
listItems = response.body ?? [];
}
}
</script>
<input type="text" oninput={(e) => search(e.currentTarget.value)} />
Explanation
An abortable fetcher object is used because abortable fetchers provide the necessary try..catch
block to trap and filter out the exception that is thrown whenever a fetch call is aborted.
A unique symbol is used here so each instance of the AutoComplete component uses a different symbol, so one autocomplete doesn't mess up with the HTTP request of another autocomplete.
When calling DrFetch.get()
, we specify the auto-abort key along with a delay in milliseconds. This delay effectively works as debouncing the request during the specified time. Now you don't even need to debounce the call yourself.
本文标签: How to handle expired http requests in SvelteStack Overflow
版权声明:本文标题:How to handle expired http requests in Svelte? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744224443a2596020.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
dr-fetch
package. I'll implement the feature in a week's time. I usually work these things over the weekends. I know you don't want an external package, but this is not a concern of Svelte. You either write the boilerplate, or you create your own wrapper in the project, or you consume an external package. – José Ramírez Commented Mar 25 at 18:25