This isn't a fully formed idea, just wanted to throw it out and see what folks think.
At the moment computed properties are always synchronous. They can of course return a promise, but that's not necessarily the most helpful thing. Luckily, now that we've jettisoned our ES5 constraint, we have a nice way of declaring an async computed property: the async keyword.
The thinking is that it would work something like this:
export default {
computed: {
// network requests
async suggestions({ search }) => {
const r = await fetch(`/api/suggestions?q=${search}`);
return await r.json();
},
// web workers
async expensiveThingToCalculate({ x }) => {
return await worker.calculateThing(x);
}
},
data() {
// default values, since they can't be computed
// before the first render
return {
suggestions: [],
expensiveThingToCalculate: -1
};
}
};
When search changed (and when the component first renders), the function would run and we'd get some suggestions. When the promise resolved, Svelte would run component.set({ suggestions }). These would be available in the template directly — no need to use an {#await ...} block, for example.
Later computations would invalidate earlier ones (e.g. if the response for q=food somehow came back before the response for the incomplete q=foo query, foo would be discarded).
An additional possibility: using the async keyword indicates that it's not essential for the property to update immediately. Svelte could potentially use requestIdleCallback under the hood to prevent computations blocking the UI.
This seems like a nice syntax but I think the thing that jumps out at me first is how would we handle promise rejections? I can't think of a good way/place to do that. I guess one option is to just say that it results in undefined behavior, similar to how (I imagine) an exception from the existing synchronous computed properties would be treated. But there are often more points of failure in asynchronous functions (network requests, etc.) and so it might be inconvenient to make users handle every possibility in each asynchronous computed property. I'm not sure what I'd want instead though.
I think async computed properties should return a promise and the async keyword just gets passed through. With the syntax already in place for using promises, it would make everything cleaner and clearer.
You mentioned "no need for an {#await} block", but it'd still be nice to be _able_ to visualize a loading anim for a suggestions update.
Perhaps that could be tracked outside of the computed property instead & be fine?
this.set({ loading:true, search:123 });
// flag "loading:false" somewhere; dont think you can do it inside computed prop
Async computed properties are possible in v3 via reactive statements.
Is there any reference how it can be done? Or rather what the "best" way is to achieve it?
I'm currently using this:
<Box list={promise.then(pkg => pkg.dependencies)}/>
and then
```svelte
{#await list then list}
{#each list as item}
{item}
{/each}
{/await}
````
But this only works because the component doesn't use it as an attribute. If your intent is to just use it as an attribute, then I have no idea and I also want to know.
let output_value;
$: {
some_async_operation(input_value).then(_ => output_value = _);
}
will re-run whenever input_value changes, and will asynchronously update output_value.
I’m a newbie, I was thinking of async attributes. Is this possible?
<a href={await href}/>
I want the element to appear first and then href be set later
@fregante for help, come and chat to us at https://svelte.dev/chat - not on closed bugs. What you are trying to achieve is https://svelte.dev/repl/bcd0c75996b44f89b95cc0e4d27e22d4?version=3.18.2
Chats are cool for support but nobody googling will find them. I don’t see this feature being documented anywhere so it’s great to see that example now.
Chats are cool for support but nobody googling will find them.
Agreed, there is a Svelte tag on StackOverflow which is good for this however. As for documentation, reactive properties are documented, but perhaps this specific usecase could be added for clarity.
Most helpful comment
Chats are cool for support but nobody googling will find them. I don’t see this feature being documented anywhere so it’s great to see that example now.