
# AbortControlleri mustrid

`AbortController` ja `AbortSignal` on Phasis-is täielikud WHATWG teostused. Ka standardi koostamise abifunktsioonid (`AbortSignal.any`, `AbortSignal.timeout`) on kaasas. See leht käsitleb levinud mustreid ja seda, kuidas tühistamine levib üle PHP piiri.

## Fetch-päringu tühistamine

```js
const ctrl = new AbortController();
const p = fetch(url, { signal: ctrl.signal });
ctrl.abort();                     // p rejects with AbortError DOMException
```

Põhjus on vaikimisi `AbortError`, kuid võite määrata ka enda oma:

```js
ctrl.abort(new Error('user cancelled'));
```

`fetch` lükatakse tagasi teie antud väärtusega.

## Ajalimiit

```js
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
```

`AbortSignal.timeout(ms)` tagastab signaali, mis katkestab ise töö pärast aega `ms`. Taimer käivitub mootori sündmussilmuse kaudu, mis juhib ka `setTimeout` / `queueMicrotask` toiminguid (vt [API: Sündmussilmus](https://phasis.inline0.dev/et/docs/api#event-loop)). Fetch-edastus kontrollib ülekande ajal signaali — vaikimisi `CurlTransport` puhul `CURLOPT_PROGRESSFUNCTION` kaudu —, seega katkestatakse päring kiiresti pärast tähtaja saabumist.

Vaikimisi kasutab tsükkel **virtuaalaega**: see viib kella järgmise ootel tähtajani, selle asemel et magada PHP, nii et `fetch(url, { signal: AbortSignal.timeout(5000) })` kas lõpetab enne tähtaega või katkestatakse järgmisel tsüklitaktil — see ei jäta PHP kunagi ootama. Reaalajas toimimiseks peab host juhtima `tickEventLoop()` käitamist seinakella järgi.

## Võidujooks: esimene katkestamine võidab

```js
const user = new AbortController();
const signal = AbortSignal.any([user.signal, AbortSignal.timeout(10_000)]);
const res = await fetch(url, { signal });
// res rejects if EITHER the user clicks cancel OR 10s elapses
```

## Leviku edasiandmine kihtide vahel

Mähi oma asünkroonne töö signaali arvestavasse tsüklisse:

```js
async function fetchPaged(url, signal) {
  const out = [];
  for (let page = 1; ; page++) {
    if (signal.aborted) throw signal.reason;
    const r = await fetch(`${url}?page=${page}`, { signal });
    const data = await r.json();
    if (data.length === 0) break;
    out.push(...data);
  }
  return out;
}
```

Päring pärib signaali otse; käsitsi tehtav `if (signal.aborted)` katab päringutevahelised pausid, mil lehe tsükkel muidu edasi töötaks.

## Katkestussündmuse kuulamine

```js
ctrl.signal.addEventListener('abort', () => {
  releaseDatabaseLock();
  cancelDownstreamWork();
});
```

`signal.reason` määratakse enne kuulajate käivitamist.

## Signaal kohandatud päringu transpordis

Kui vahetate transpordi välja `setFetchTransport()` kaudu, antakse signaal teie väljakutsutavale funktsioonile kui `JsObject`. Arvestage sellega, kontrollides seda perioodiliselt:

```php
$engine->setFetchTransport(function (array $req, $signal) {
    $ch = curl_init($req['url']);
    // ...
    if ($signal !== null) {
        curl_setopt($ch, CURLOPT_PROGRESSFUNCTION,
            fn () => $signal->get('aborted')->value ? 1 : 0);
        curl_setopt($ch, CURLOPT_NOPROGRESS, false);
    }
    $body = curl_exec($ch);
    if (curl_errno($ch) === CURLE_ABORTED_BY_CALLBACK) {
        throw new \Phasis\BuiltIn\Fetch\TransportException(
            'aborted', 'aborted',
        );
    }
    // ...
});
```

`kind: 'aborted'` abil `TransportException` viskamine paneb JS-poole `fetch`-i tagasi lükkama veaga `AbortError DOMException` — sama juhtub siis, kui spetsifikatsioonikohane katkestustsükkel oleks käivitunud.

Natiivset katkestamist toetavate taustateenuste puhul (Guzzle `on_progress`, Symfony `ResponseInterface::cancel`) kasutage sama perioodilise kontrolli ja vea viskamise mustrit.

## Mustreid, mis veel ei tööta

- **`signal.addEventListener('abort', () => fetch(cleanupUrl))`** — kuulaja käivitatakse sünkroonselt; puhastuspäring küll algab, kuid katkestuse töötlemise ajal ei jõua lõpule. Ajastage see ümbritseva `await` kaudu.

`setTimeout(() => ctrl.abort(), N)` töötab (taimerite perekond on kaasas ja WPT-ga kaetud), kuid `AbortSignal.timeout(N)` on lühem ja väljendab kavatsust paremini, kui soovite vaid tähtaja saabudes katkestava signaali.

## Vt ka

- [Päringutransport](https://phasis.inline0.dev/et/docs/interop/fetch-transport) — kohandatud transpordi täielik päringu, vastuse ja signaali liides.
- [Veebi API-d (WPT)](https://phasis.inline0.dev/et/docs/compatibility/web-apis) — AbortControlleri ja AbortSignali WPT läbimise määr.
