RORK LABEN
MAX — Rork Maxは全Appleプラットフォーム向けにネイティブSwiftアプリを生成します。iPhone・iPad・Apple Watch・Apple TV・Vision Proに対応しますPUBLISH — Rork MaxはXcodeなしで2クリックのApp Store公開に対応します。ビルドから申請までの手数を大きく減らせますFUND — Rorkはa16zから280万ドルを調達しました。月間743,000訪問・成長率85%と、利用が広がっていますNATIVE — Rorkは自然言語の指示からReact Native(Expo)のネイティブアプリを生成します。カメラや通知などデバイス機能も扱えますOWN — 生成されたコードは完全に自分のものになります。あとから手を入れて拡張していけますMVP — Rorkは動くMVPを数週間ではなく数時間で用意できます。アイデアの検証を素早く回せますMAX — Rork Maxは全Appleプラットフォーム向けにネイティブSwiftアプリを生成します。iPhone・iPad・Apple Watch・Apple TV・Vision Proに対応しますPUBLISH — Rork MaxはXcodeなしで2クリックのApp Store公開に対応します。ビルドから申請までの手数を大きく減らせますFUND — Rorkはa16zから280万ドルを調達しました。月間743,000訪問・成長率85%と、利用が広がっていますNATIVE — Rorkは自然言語の指示からReact Native(Expo)のネイティブアプリを生成します。カメラや通知などデバイス機能も扱えますOWN — 生成されたコードは完全に自分のものになります。あとから手を入れて拡張していけますMVP — Rorkは動くMVPを数週間ではなく数時間で用意できます。アイデアの検証を素早く回せます
記事一覧/開発ツール
開発ツール/2026-07-24上級

同じ通信が同時に何本も飛ぶのを1本に束ねる — 参照カウント付きシングルフライト層の設計

起動直後に同じ API へ何本ものリクエストが同時に飛ぶ多重フェッチを、進行中の Promise を共有して1本に束ねる設計です。失敗した Promise を配り続けてしまう罠、呼び出し側の中断が全体を巻き込む罠を避ける、参照カウント付きシングルフライト層の実装を、実際の通信ログとともに残します。

Rork519React Native211API6パフォーマンス31アーキテクチャ20

プレミアム記事

夜、リリース直後の壁紙アプリをネットワークインスペクタにつないで開いた瞬間、同じ URL の行が続けざまに並びました。/me/entitlements が、わずか 200ms ほどのあいだに 4 本。どれも中身は同じで、返ってくる JSON も同じでした。

胸の奥がざわつきました。無駄な通信が 4 倍になるだけならまだしも、同じ端末で 3 本の 401 が重なった直後、ユーザーの何人かが不意にログアウトさせられていたのです。トークンの期限切れに対して 3 本が同時に更新をかけ、後から完了した更新が先に発行されたトークンを無効化していました。

原因は 1 画面ではありませんでした。ホーム、お気に入りバッジ、課金ゲート — 別々のコンポーネントが、それぞれ「自分が必要だから」と同じ取得を独立に走らせていただけです。誰も、隣がすでに同じものを取りにいっていることを知りませんでした。

取り上げたいのは、この「同時多発する同一リクエスト」を、進行中の 1 本に束ねる設計です。個人開発で 6 本のアプリを同じ通信基盤で回している中で、あの夜のあとに実際へ入れて運用しているコードをもとにしています。難しい仕組みではありません。けれど、素直に書くと必ず踏む罠が二つあり、そこを抜けて初めて実用になります。

なぜ同じリクエストが同時に飛ぶのか

React Native のアプリでは、画面がマウントされた瞬間に各コンポーネントの useEffect が走ります。同じデータを必要とする複数のコンポーネントが同時に現れると、それぞれが独立に fetch を発行します。

Rork が生成する取得コードは、たいていコンポーネントの内側で完結しています。次のような形です。

function useEntitlements() {
  const [data, setData] = useState<Entitlements | null>(null);
  useEffect(() => {
    fetch(`${API}/me/entitlements`, {
      headers: { Authorization: `Bearer ${token}` },
    })
      .then((r) => r.json())
      .then(setData);
  }, []);
  return data;
}

このフックを 3 つのコンポーネントが呼べば、fetch は 3 本走ります。各フックは自分のローカル状態しか見ておらず、「同じ取得がすでに進行中かどうか」を共有する場所がどこにもありません。

キャッシュを挟めばいいのでは、と最初は考えました。けれど、初回の起動直後はキャッシュが空です。全員がほぼ同時に「キャッシュが無い」と判断し、そろって取得に走ります。キャッシュが埋まるのは全員が投げ終えた後で、間に合いません。守るべきは「結果の保存」ではなく、「進行中の 1 本を共有すること」でした。

シングルフライトの核 — 進行中の Promise を共有する

やることは一つです。あるキーに対する取得がすでに進行中なら、新しい fetch を投げず、進行中の Promise をそのまま返す。これをシングルフライト、あるいはリクエストのコアレッシング(束ねること)と呼びます。

最小の形はこれだけです。

const inflight = new Map<string, Promise<unknown>>();
 
function coalesce<T>(key: string, run: () => Promise<T>): Promise<T> {
  const existing = inflight.get(key);
  if (existing) return existing as Promise<T>;
 
  const promise = run();
  inflight.set(key, promise as Promise<unknown>);
  return promise;
}

キーは「何を取りにいくか」を一意に表す文字列にします。GET /me/entitlements のように、メソッドとパスを組み合わせるのが分かりやすい形です。同じキーで 4 回呼ばれても、run() が実際に走るのは最初の 1 回だけになります。

ここまでは素直です。問題は、この Map からいつエントリを消すか。ここに最初の罠があります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
起動時に同一 GET が多重に飛ぶのを、進行中の Promise を共有して1本へ束ねるシングルフライト層の実装
失敗した Promise が次回以降の呼び出しにも配られ続ける罠と、settle 時に必ず消す書き方
呼び出し側1つの中断が共有リクエスト全体を巻き込まないための、参照カウント付き AbortController
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-07-24
アプリの設定値を三層で解決する — 既定・ユーザー・リモートを境界付きにマージするレイヤー設計
既定値・ユーザー設定・リモート設定をひとつの型安全なレイヤーでマージする設計です。壊れたリモート値でもアプリが崩れないよう、キーごとに上書きの強さを変え、境界クランプと検証を通す実装を、実際の事故から起こしたコードで解説します。
開発ツール2026-07-14
AI再生成に壊されない設計 — Rork の生成コードと手書きロジックを分ける境界の引き方
Rork へ追加指示を出すたびに手書きのロジックが消える。プロンプトで守るのは対症療法です。生成コードと自分の所有コードを層で分け、再生成が届かない境界を設計で引く方法を、Zustand と service 層の実装例つきでお伝えします。
開発ツール2026-07-14
Rork が生成した fetch コードに、Zod の検証境界を1枚だけ挟む
Rork が生成したネットワークコードは、レスポンスの形を暗黙に信頼します。APIが変わると画面は静かに真っ白になります。生成UIとネットワークの間にZodのparse層を1枚だけ差し込み、壊れ方を予測可能にする実装を、実運用の数値とともに紹介します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →