AbortControllerを知らない
James Reed
Infrastructure Engineer · Leapcell

多くの開発者はAbortController
を理解していると思っているかもしれませんが、その機能は基本的なものをはるかに超えています。fetch
リクエストのキャンセルから、イベントリスナーやReactフックの管理まで。
AbortController
がどれほど強力か、本当に知っていますか?見てみましょう。
AbortControllerを使ったfetch
リクエストのキャンセル
fetch
でAbortController
を使うのは、もちろん最も一般的な使い方です。
AbortController
を使ってキャンセル可能なfetch
リクエストを作成する方法を示す例を以下に示します。
fetchButton.onclick = async () => { const controller = new AbortController(); // キャンセルボタンを追加 abortButton.onclick = () => controller.abort(); try { const response = await fetch('/json', { signal: controller.signal }); const data = await response.json(); // ここでビジネスロジックを実行 } catch (error) { const isUserAbort = error.name === 'AbortError'; // AbortErrorは、AbortControllerを使用してリクエストがキャンセルされた場合にスローされます } };
上記の例は、AbortController
の導入前には不可能だったこと、つまりネットワークリクエストをプログラムでキャンセルする機能を示しています。キャンセルされると、ブラウザはfetch
を停止し、ネットワーク帯域幅を節約します。重要なのは、キャンセルがユーザーによって開始される必要がないことです。
controller.signal
はAbortSignal
オブジェクトを提供し、fetch
のような非同期操作との通信を可能にし、それらをキャンセルできるようにします。
複数のシグナルを単一のシグナルに結合するには、AbortSignal.any()
を使用できます。使い方は次のとおりです。
try { const controller = new AbortController(); const timeoutSignal = AbortSignal.timeout(5000); const response = await fetch(url, { // いずれかのシグナルがトリガーされた場合、fetchを中止 signal: AbortSignal.any([controller.signal, timeoutSignal]), }); const data = await response.json(); } catch (error) { if (error.name === 'AbortError') { // キャンセルをユーザーに通知 } else if (error.name === 'TimeoutError') { // タイムアウトをユーザーに通知 } else { // ネットワークの問題など、他のエラーを処理 console.error(`Type: ${error.name}, Message: ${error.message}`); } }
AbortController
とAbortSignal
の違い
- AbortController:
controller.abort()
を介して、関連するシグナルを明示的にキャンセルするために使用されます。 - AbortSignal: シグナルオブジェクトを表します。直接何かをキャンセルすることはできませんが、中止された状態を伝えます。
AbortSignal
では、次のことができます。
signal.aborted
を使用して中止されたかどうかを確認します。abort
イベントをリッスンします。
if (signal.aborted) { } signal.addEventListener('abort', () => {});
AbortController
を使用してリクエストがキャンセルされると、サーバーはそれを処理したり、応答を送信したりせず、帯域幅を節約し、同時接続を減らすことでクライアント側のパフォーマンスを向上させます。
AbortControllerの一般的なユースケース
WebSocket接続のキャンセル
WebSocketのような古いAPIは、ネイティブでAbortSignal
をサポートしていません。代わりに、次のようにキャンセルを実装できます。
function abortableSocket(url, signal) { const socket = new WebSocket(url); if (signal.aborted) { socket.close(); // すでにキャンセルされている場合はすぐに中止 } signal.addEventListener('abort', () => socket.close()); return socket; }
注:AbortSignal
がすでに中止されている場合、abort
イベントはトリガーされないため、このケースを事前に確認して処理する必要があります。
イベントリスナーの削除
従来、イベントリスナーを削除するには、まったく同じ関数参照を渡す必要があります。
window.addEventListener('resize', () => doSomething()); window.removeEventListener('resize', () => doSomething()); // これは機能しません
AbortController
を使用すると、これが簡単になります。
const controller = new AbortController(); const { signal } = controller; window.addEventListener('resize', () => doSomething(), { signal }); // abort()を呼び出してイベントリスナーを削除 controller.abort();
古いブラウザの場合は、AbortController
をサポートするためにポリフィルを追加することを検討してください。
Reactフックでの非同期タスクの管理
Reactでは、以前の非同期タスクが完了する前にコンポーネントが更新されると、エフェクトが誤って並行して実行される可能性があります。
function FooComponent({ something }) { useEffect(async () => { const data = await fetch(url + something); // データを処理 }, [something]); return <>...</>; }
このような問題を回避するには、AbortController
を使用して以前のタスクをキャンセルします。
function FooComponent({ something }) { useEffect(() => { const controller = new AbortController(); const { signal } = controller; (async () => { const data = await fetch(url + something, { signal }); // レスポンスを処理 })(); return () => controller.abort(); }, [something]); return <>...</>; }
Node.jsでのAbortControllerの使用
最新のNode.jsには、AbortController
と互換性のあるsetTimeout
実装が含まれています。
const { setTimeout: setTimeoutPromise } = require('node:timers/promises'); const controller = new AbortController(); const { signal } = controller; setTimeoutPromise(1000, 'foobar', { signal }) .then(console.log) .catch((error) => { if (error.name === 'AbortError') console.log('Timeout was aborted'); }); controller.abort();
ブラウザのsetTimeout
とは異なり、この実装はコールバックを受け入れません。代わりに、.then()
またはawait
を使用します。
高度なスケジューリングのためのTaskController
ブラウザは、タスクの優先順位付けのためにscheduler.postTask()
に移行しており、TaskController
はAbortController
を拡張しています。これを使用して、タスクをキャンセルしたり、優先度を動的に調整したりできます。
const taskController = new TaskController(); scheduler .postTask(() => console.log('Executing task'), { signal: taskController.signal }) .then((result) => console.log(result)) .catch((error) => console.error('Error:', error)); taskController.abort();
優先度制御が必要ない場合は、代わりにAbortController
を使用できます。
結論
AbortController
は、最新のJavaScript開発における不可欠なツールであり、非同期タスクを管理およびキャンセルするための標準化された方法を提供します。
ブラウザとNode.jsの両方の環境への統合は、その汎用性と重要性を強調しています。
AbortController
を知らない場合は、今こそそのすべての機能を理解し、非同期プログラミングツールキットの基礎にすべき時です。
Leapcellは、Node.jsプロジェクトをクラウドにデプロイするための最適な選択肢です。
Leapcellは、Webホスティング、非同期タスク、およびRedis向けの次世代サーバーレスプラットフォームです。
多言語サポート
- Node.js、Python、Go、またはRustで開発します。
無制限のプロジェクトを無料でデプロイ
- 使用量に対してのみ支払い - リクエストも料金もかかりません。
比類のない費用対効果
- アイドル料金なしの従量課金制。
- 例:25ドルで平均応答時間60msで694万リクエストをサポートします。
合理化された開発者エクスペリエンス
- 簡単なセットアップのための直感的なUI。
- 完全に自動化されたCI / CDパイプラインとGitOps統合。
- 実用的な洞察のためのリアルタイムメトリックとロギング。
簡単なスケーラビリティと高性能
- 高い同時実行性を容易に処理するための自動スケーリング。
- 運用オーバーヘッドはゼロ - 構築に集中するだけです。
詳細については、ドキュメントをご覧ください。
Xでフォローしてください:@LeapcellHQ