Data that arrives in the same response
Load page data with an async computed value inside @try, and the server sends it in the same response.
Last page, a click asked the server for the next page. So what happens when that page waits for slow data?
There is no special loader function. A page loads data the way any component does: an async computed() inside @try.
Think of a restaurant that brings your bread first. The main dish comes later, to the same table. This is an analogy.
Press Next to step through one page load.
What does the page show while its data loads?
Drag the timeline or press Next. Then switch to Quick data and compare.
One request goes out. The page file runs and starts to load the greeting.
The browser is waiting for the first part.
export default function Feed({ url }: PageProps) @{ (runs for /feed) const data = computed(async () => slowGreeting(url.pathname)); (starts loading) <main> <h1>Feed</h1> @try { <p>{data.text}</p> } @pending { <p>Loading...</p> } @catch { <p>Failed</p> } </main>}- noteThe browser asked for
/feed. This is the only request.
Simplified. This is a multi-page app made with the router, so a server makes each page. Markless itself does not need a server. We ran this page in an app made from the full-stack starter. With slow data, the heading and Loading... came first, and the greeting came later in the same response. With quick data, the greeting came in the first part.
Notice that the data comes in the same response. The browser makes no second request.
The code
import { computed } from '@markless/core';
import type { PageProps } from '@markless/router';
import { slowGreeting } from '../lib/slow.ts';
export default function Feed({ url }: PageProps) @{
const data = computed(async () => slowGreeting(url.pathname));
<main>
<h1>Feed</h1>
@try {
<p>{data.text}</p>
} @pending {
<p>Loading...</p>
} @catch {
<p>Failed</p>
}
</main>
}
If slowGreeting is slow, one response comes in two parts:
- The heading and the
@pendingcontent come first. - When the data is ready, the same response adds the
@trycontent. The page puts it in place, and the response ends.
If the data is ready quickly, the server puts it in the first part. You turn nothing on.
For the rules of async values, see Async.
Coming from another framework?
The router has no loader or action export. A page gets only params, url, and status as props. Data comes from async values in the page, and slow parts stream in the same response.
Next: What if the data comes from your own server? API routes →
