All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
4.9 KiB
4.9 KiB
HTTP Requests: req( )
The req function creates a reactive HTTP request controller. It returns signals for loading, error, and data, plus a run method to execute the request and an abort method to cancel it. All signals update automatically as the request progresses.
Function Signature
req(config: {
url: string;
method?: string; // default: 'GET'
headers?: Record<string, string>;
}): {
run: (body?: any) => Promise<any>;
abort: () => void;
loading: Signal<boolean>;
error: Signal<string | null>;
data: Signal<any | null>;
}
| Parameter | Type | Required | Description |
|---|---|---|---|
url |
string |
Yes | The endpoint to call. |
method |
string |
No | HTTP method ('GET', 'POST', etc.). Default 'GET'. |
headers |
object |
No | Custom headers (will be merged with defaults). |
Returns: A controller object with reactive signals and methods.
Usage Patterns
1. Basic GET Request
const users = req({ url: '/api/users' });
// Start the request
users.run().catch(console.error);
// React to the response
watch(() => {
if (users.loading()) console.log('Loading...');
if (users.error()) console.error(users.error());
if (users.data()) console.log('Data:', users.data());
});
2. POST Request with Body
const createUser = req({ url: '/api/users', method: 'POST' });
const handleSubmit = async (formData) => {
try {
await createUser.run(formData);
alert('User created!');
} catch (err) {
// Error already in createUser.error()
}
};
3. Aborting a Request
const search = req({ url: '/api/search' });
// Abort if the user types again quickly
let timeout;
input({ onInput: (e) => {
clearTimeout(timeout);
search.abort(); // cancel previous in-flight request
timeout = setTimeout(() => search.run({ q: e.target.value }), 300);
}});
4. Reactive UI with Signals
const profile = req({ url: '/api/me' });
const App = () =>
div([
when(() => profile.loading(),
() => div("Loading...")
),
when(() => profile.error(),
() => div("Error: " + profile.error())
),
when(() => profile.data(),
() => div([
h2(profile.data().name),
p(profile.data().email)
])
)
]);
profile.run();
mount(App, '#app');
Request Lifecycle
When you call run(body?):
- Any previous request is aborted automatically.
loadingbecomestrue.erroris cleared.- A 10‑second timeout is set (auto‑abort).
- The request is sent using
fetch. - On success:
datais set with the parsed JSON,loadingbecomesfalse. - On error:
erroris set with the message,datais cleared,loadingbecomesfalse.
Important: The response body is parsed as JSON. If the response is not OK or the JSON parsing fails,
erroris set and the promise rejects.
Automatic Headers
- If
bodyis a plain object or array, the request automatically includesContent-Type: application/json(unless you override it inheaders). - If
bodyis aFormDatainstance, theContent-Typeis not set (browser will set it automatically with the correct boundary). - Other headers can be added via the
headersoption.
const upload = req({
url: '/upload',
method: 'POST',
headers: { 'X-Custom': 'value' }
});
const formData = new FormData();
formData.append('file', fileInput.files[0]);
upload.run(formData);
Error Handling
- Network errors, timeouts, and HTTP error statuses (4xx, 5xx) all set
errorand cause the promise to reject. - The
errorsignal contains a human‑readable message. - Abort errors (calling
abort()or timeout) are silent – they do not seterroror reject the promise?
Actually, according to the source: ife.name === 'AbortError', it does not callerror(e.message), but the promise still rejects with the AbortError. You can handle it with.catch()if needed.
Complete Example
const api = req({ url: 'https://jsonplaceholder.typicode.com/posts/1' });
const App = () =>
div({ class: "demo" }, [
when(() => api.loading(), () => p("⏳ Loading...")),
when(() => api.error(), () => p("❌ " + api.error())),
when(() => api.data(), () => div([
h2(api.data().title),
p(api.data().body)
])),
button({
onClick: () => api.run(),
disabled: () => api.loading()
}, "Fetch")
]);
mount(App, '#app');
Summary
| Member | Type | Description |
|---|---|---|
run(body?) |
(any) => Promise |
Starts the request. Returns a promise. |
abort() |
() => void |
Cancels the current request. |
loading |
Signal<boolean> |
true while request is in flight. |
error |
Signal<string|null> |
Contains an error message, or null. |
data |
Signal<any|null> |
Contains the parsed response (JSON), or null. |