JavaScript Tips | 基本・共通ユーティリティ:環境 - オンライン状態判定

JavaScript JavaScript
スポンサーリンク

なぜ「オンライン状態判定」ユーティリティが業務で重要なのか

業務システムでも、ユーザーは常に安定したネットワーク環境にいるとは限りません。
社内 Wi-Fi が不安定、移動中のモバイル回線、一瞬だけオフラインになる、などは普通に起きます。

ここで問題になるのは、

オンライン前提で API を叩きに行ってエラーだらけになる
オフラインなのに「保存しました」と表示してしまう
一時的な切断でユーザーの入力内容が消えてしまう

といった「ユーザー体験として痛い」状況です。

これを避けるために必要なのが、
「今オンラインかどうか」「オンライン/オフラインが切り替わった瞬間」
を扱うための「オンライン状態判定ユーティリティ」です。


一番基本の情報源:navigator.onLine

今オンラインかどうかを一発で知る

ブラウザには、navigator.onLine というプロパティがあります。

console.log(navigator.onLine); // true または false
JavaScript

意味としては、

true → 「ネットワークに接続されている“っぽい”」
false → 「明らかにオフライン」

です。

ここで大事なのは、
true だからといって「必ず API が成功する」とは限らない
という点です。

オンライン判定はあくまで「目安」であり、
最終的には API 呼び出しの成否で判断する必要があります。
それでも、「オフラインが明らかな場合に無駄なリクエストを避ける」には十分役に立ちます。


オンライン状態判定ユーティリティの基本形

今の状態を返す小さな関数

まずは、navigator.onLine を安全にラップした関数を用意します。

function isOnline() {
  if (typeof navigator === "undefined") {
    return true; // サーバーサイドなどでは「オンライン扱い」にしておく
  }

  if (typeof navigator.onLine !== "boolean") {
    return true; // 情報が取れない環境では「オンライン扱い」にしておく
  }

  return navigator.onLine;
}
JavaScript

使い方はとてもシンプルです。

if (isOnline()) {
  console.log("オンラインなので API を叩く");
} else {
  console.log("オフラインなのでキューにためる");
}
JavaScript

ここでの重要ポイントは、

navigator がない環境(SSR など)でも落ちないようにしている
navigator.onLine が使えない環境では「とりあえずオンライン扱い」にしている

という「壊れないための配慮」をユーティリティ側に閉じ込めていることです。


オンライン/オフラインの変化を検知する

window の online / offline イベント

「今オンラインかどうか」だけでなく、
「オンラインになった瞬間」「オフラインになった瞬間」を知りたい場面も多いです。

ブラウザは、次のイベントを発火してくれます。

window.addEventListener("online", handler)
window.addEventListener("offline", handler)

これをラップして、
「購読・解除しやすいユーティリティ」にしておくと便利です。

function subscribeOnlineStatus(onChange) {
  if (typeof window === "undefined") {
    return () => {};
  }

  const handleOnline = () => onChange(true);
  const handleOffline = () => onChange(false);

  window.addEventListener("online", handleOnline);
  window.addEventListener("offline", handleOffline);

  // 初期状態も通知しておく
  onChange(isOnline());

  // 解除用の関数を返す
  return () => {
    window.removeEventListener("online", handleOnline);
    window.removeEventListener("offline", handleOffline);
  };
}
JavaScript

使い方のイメージはこうです。

const unsubscribe = subscribeOnlineStatus((online) => {
  console.log("オンライン状態:", online);
});

// もういらなくなったら
// unsubscribe();
JavaScript

ここでの深掘りポイントは、

「イベント登録」と「解除」をセットでユーティリティに閉じ込めていること
初期状態も onChange に流しているので、呼び出し側が「最初の状態」を気にしなくていいこと

です。


実務での具体的な利用イメージ

例1: オフライン時は「保存ボタン」の挙動を変える

ユーザーがフォームを入力している画面を想像してください。
オンラインなら普通に API に保存し、
オフラインなら「ローカルに一時保存して、オンラインになったら同期する」
という挙動にしたいとします。

let latestOnline = isOnline();

subscribeOnlineStatus((online) => {
  latestOnline = online;
  renderOnlineBadge(online); // 画面上の「オンライン/オフライン」表示を更新
});

async function onClickSave(formData) {
  if (latestOnline) {
    await saveToServer(formData);
    alert("サーバーに保存しました");
  } else {
    saveToLocalStorage(formData);
    alert("オフラインのためローカルに保存しました");
  }
}
JavaScript

ここでのポイントは、

「オンラインかどうか」の判定を一箇所に集約している
ボタン側は latestOnline だけを見ればよく、navigator.onLine を直接触らない

という構造になっていることです。

例2: オフライン中にたまったキューをオンライン復帰時に送信する

例えば、「操作ログ」や「イベント」をサーバーに送る仕組みを考えます。
オフライン中はキューにためておき、
オンラインに戻ったらまとめて送信する、というパターンです。

const queue = [];

function enqueueEvent(event) {
  queue.push(event);
}

async function flushQueue() {
  if (!isOnline()) return;
  if (queue.length === 0) return;

  const payload = [...queue];
  queue.length = 0;

  try {
    await fetch("/api/events", {
      method: "POST",
      body: JSON.stringify(payload),
      headers: { "Content-Type": "application/json" },
    });
  } catch (e) {
    // 失敗したらキューを戻す
    queue.unshift(...payload);
  }
}

subscribeOnlineStatus((online) => {
  if (online) {
    flushQueue();
  }
});
JavaScript

これで、

オンライン中 → その場で送る(あるいはすぐ flush)
オフライン中 → キューにためる
オンライン復帰 → 自動で flush

という流れを作れます。


「オンライン判定」に頼りすぎない、という視点も大事

最後に、少しだけ現実的な話をしておきます。

navigator.onLine は便利ですが、
「true だから必ず通信成功する」「false だから絶対に失敗する」
というほど厳密なものではありません。

例えば、

Wi-Fi にはつながっているが、インターネットには出られない
企業プロキシや VPN の影響で、一部の API だけ失敗する

といったケースでは、navigator.onLine は true のままでも通信が失敗します。

なので、設計としてはこう考えるのが健全です。

isOnline() → 「明らかにオフラインなら無駄なリクエストを避けるための“ヒント”」
実際の API 呼び出し → 成否を必ず try/catch で確認する

オンライン状態判定ユーティリティは、
「ユーザー体験を少し賢くするための補助輪」であって、
エラー処理そのものの代わりにはならない、という感覚を持っておくとバランスが良くなります。

タイトルとURLをコピーしました