ข้ามไปยังเนื้อหา

Async Patterns

นักพัฒนา React track async state ด้วยมือ: useState สามตัวสำหรับ loading, data, และ error แล้วต่อด้วย if/else chain ใน JSX React 18 เพิ่ม <Suspense> และ error boundary เพื่อทำให้ declarative ขึ้น แต่ต้อง setup เพิ่มและต้องใช้ data library ที่ throw Promise ได้

Svelte มีคำตอบเดียวที่หรูหรา ฝังอยู่ใน template syntax:

{#await promise}
<!-- loading -->
{:then value}
<!-- resolved -->
{:catch err}
<!-- rejected -->
{/await}

บล็อกเดียว สามสถานะ ไม่มี hook ไม่มี error boundary component ไม่มีการ throw Promise ถ้าตัวแปร promise ถูกแทนที่ด้วย Promise ใหม่ (เช่น เมื่อผู้ใช้กด “Reload”) Svelte จะกลับเข้าสถานะ loading ให้อัตโนมัติ

React
function UserCard({ userId }) {
const [user, setUser] = React.useState(null);
const [loading, setLoading] = React.useState(true);
const [error, setError] = React.useState(null);
React.useEffect(() => {
setLoading(true);
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => { setUser(data); setLoading(false); })
.catch(err => { setError(err.message); setLoading(false); });
}, [userId]);
if (loading) return <p>Loading...</p>;
if (error) return <p style={{ color: 'red' }}>Error: {error}</p>;
return <div><h2>{user.name}</h2><p>{user.email}</p></div>;
}
Svelte
<script>
let { userId } = $props();
async function loadUser(id) {
const res = await fetch(`/api/users/${id}`);
if (!res.ok) throw new Error('Not found');
return res.json();
}
let userPromise = $derived(loadUser(userId));
</script>
{#await userPromise}
<p>Loading...</p>
{:then user}
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
</div>
{:catch err}
<p style="color:red">Error: {err.message}</p>
{/await}

เมื่อ userId เปลี่ยน $derived จะสร้าง Promise ใหม่ และ {#await} จะกลับเข้าสถานะ pending ทันที ไม่ต้อง reset state ด้วยมือ

React
// React — requires library support (react-query, SWR, Relay)
// The library must throw a Promise for Suspense to catch
<Suspense fallback={<Spinner />}>
<ErrorBoundary fallback={<ErrorUI />}>
<UserCard userId={1} />
</ErrorBoundary>
</Suspense>
Svelte
<!-- Svelte — no extra library, no boundary components -->
{#await userPromise}
<Spinner />
{:then user}
<UserCard {user} />
{:catch err}
<ErrorUI message={err.message} />
{/await}

Demo นี้ใช้ setTimeout จำลอง network call 500 ms ที่บางครั้ง reject กดปุ่ม “Load” เพื่อสร้าง Promise ใหม่ — {#await} จัดการทั้งสามสถานะให้อัตโนมัติ

syntax ที่ถูกต้องสำหรับสามส่วนของบล็อก {#await} คืออะไร?
เกิดอะไรขึ้นใน Svelte เมื่อคุณ assign Promise ใหม่ให้ตัวแปรที่ใช้ใน {#await}?
{#await} คล้ายกับแนวทาง Suspense ของ React อย่างไร?
คุณต้องการข้าม loading state และแสดงแค่ resolved value เท่านั้น shorthand ไหนใช้ได้?