-
-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
"finally" after await block #5695
Comments
I'm -1 on this. This feels like adding a feature for the sake of parity with the Promise API, and not for the sake of what's generally useful. The situations where you'll want to have content that appears once a promise settles directly following content that appears when it resolves/rejects seem fairly specific. And you could achieve the same result with another |
Those are fair points. Thanks for considering this suggestion anyways! |
Nice idea @ItalyPaleAle. I think that parity with the Promise API is what gives #await 100% of its value. The functionality that it offers can be achieved via other methods, so its value is derived completely from the reduction in code and complexity that results from such a close to match the API. It makes sense that #await would match the execution flow of promises as closely as possible. |
I agree that I am missing {:finally} it's a bit strange that you'd have to go with workarounds when I thought svelte was all about elegance and simplicity. |
This has gotten three thumbs down from maintainers, and I am going to close it. I will also note that adding a feature that lets you write less code in a certain situation is not an example elegance or simplicity if it's a rather uncommon situation. |
I would like to add my own +1 here and point out that in several other feature suggestions I've seen, parity with the native APIs is often used as strong grounds for/against implementing a feature. I think the same should be true here. Finally was implemented as part of the official JavaScript spec because TC39 discussed it at length and found it to be generally useful. I could be mistaken about the spec and approval process here, but this is how I understand it. The same concept applied to Svelte's <script>
async function getRandomNumber() {
const res = await fetch(`https://svelte.dev/tutorial/random-number`);
const text = await res.text();
if (res.ok) {
return text;
} else {
throw new Error(text);
}
}
let promise = getRandomNumber();
function handleClick() {
promise = getRandomNumber();
}
</script>
<button on:click={handleClick}>
generate random number
</button>
{#await promise}
<p>...waiting</p>
{:then number}
<p>The number is {number}</p>
{:catch error}
<p style="color: red">{error.message}</p>
{:finally}
The operation has concluded.
{/await} Here is a REPL demonstrating the same logic using the existing In this workaround, a boolean value, defaulted to I'm sure there is probably a better way to demonstrate this, but I think the REPL linked above sufficiently serves to demonstrate the desired functionality. |
@Rich-Harris You asked me to raise an issue for this a while back (Twitter comment), hence my comment, but I haven't received any reply for this yet. Should I open a new/duplicate issue. |
I think Svelte should have a {:finally} It's a pain to do it manually with a workaround, and not a big deal to add it as a feature and it seems more elegant to have it. +1 for having it |
I personally +1 this since:
In the meantime for those who came here looking for an quick workaround, here it is a simple drop-in component that achieves the same result. Component:Await.svelte <!--
@component
Adds an additional `finally` slot to the typical `{#await expression}...{:then name}...{:catch name}...{/await}` block.
-->
<script lang="ts">
/** The promise to be awaited. */
export let promise: Promise<unknown>;
</script>
{#await promise}
<slot name="await" />
{:then result}
<slot name="then" {result} />
<slot name="finally" {result} error={undefined} />
{:catch error}
<slot name="catch" {error} />
<slot name="finally" {error} result={undefined} />
{/await} Usage example:App.svelte <script lang="ts">
import Await from './Await.svelte';
let myPromise: Promise<unknown>;
</script>
<Await promise={myPromise}>
<div slot="await">
<p>processing...</p>
</div>
<div slot="catch" let:error={error}>
<p>{error.message}</p>
</div>
<div slot="then" let:result={result}>
<p>{result}</p>
</div>
<div slot="finally" let:error={error} let:result={result}>
<p>{error.message}</p> <!-- undefined on success -->
<p>{result}</p> <!-- undefined on fail -->
</div>
</Await> Not a perfect solution, syntax is more bloated but it does the trick for me ¯\_(ツ)_/¯ |
+1 for creative workaround :) |
Agree using all of Eg. consider this code where I swap a search icon with a loading spinner: <div class="input-group>
<span class="input-group-text">
{#await searching}
<div class="spinner-border spinner-border-sm" role="status">
<span class="visually-hidden">Loading...</span>
</div>
{:then}
<i class="bi bi-search"></i>
{:catch}
<i class="bi bi-search"></i>
{/await}
</span>
<input
type="text"
class="form-control"
class:disabled
on:input={handleInput}
bind:value={query}
placeholder={'Search by name or email address'}
{disabled}
/>
</div>
<!-- error handled elsewhere -->
{#if errorMessage}
<div class="invalid-feedback d-block">{errorMessage}</div>
{/if} Would be nicer as {#await loading}
<!-- spinner -->
{:finally}
<!-- search icon -->
{/if} |
Describe the solution you'd like
In Svelte 3, the syntax for await blocks is modeled after the one for promises:
await … then … catch
.In the specification for
Promise
, however, there's also one more callback: finally. This is executed after thethen
orcatch
callbacks, regardless of whether the Promise was fulfilled or rejected. Note that per specs,finally
callbacks do not receive any argument.How important is this feature to you?
Not incredibly important, but it would allow reducing code duplication. For example, look at this:
Without
{:finally}
, we'd have to add the last sentence to both the{:then}
and{:catch}
blocksThe text was updated successfully, but these errors were encountered: