Apex

Visualforceページを一定間隔で自動更新して結果を表示する方法

処理の途中経過を画面に出し続けたいとき、ページ全体を作り直すリロードは重すぎます。Visualforceにはこのための部品があります。actionPollerの間隔設定と、ビューステートとの付き合いかたを書きます。

2023.02.27

なぜ自動更新が要るのか

バッチや非同期処理の進み具合を、ユーザーが操作しなくても画面に反映したい場面があります。JavaScript remotingでApexを呼び、結果が返るたびにlocation.reload()でページ全体を読み込み直す方法も動きますが、毎回ページ全体の表示状態を作り直すため、一部の表示だけ更新したい用途には重すぎます。

Visualforceには、この用途のための標準コンポーネントapex:actionPollerがあります。指定した間隔でコントローラのメソッドを呼び、指定した範囲だけを再描画します。本記事はこちらを使う方法で書きます。

apex:actionPollerの仕組み

属性役割
action呼び出すコントローラのメソッド
interval呼び出す間隔(秒)。最小値は5秒、指定しない場合の既定値は60秒です
reRender再描画するコンポーネントのID
enabledfalseにすると呼び出しを止めます
status通信状態と連動させるapex:actionStatusのID
actionPollerのactionに指定するのは、通常のコントローラメソッド(戻り値なしのpublicメソッド、またはPageReferenceを返すメソッド)です。JavaScript remoting専用の@RemoteActionメソッドは指定できません。

⚠️ 公式ドキュメントは、actionPollerで呼ぶメソッドを軽量にするよう求めています。DMLや外部サービスの呼び出しのような重い処理をactionPoller経由で毎回実行すると、ポーリングのたびにその処理が走り、サーバー負荷とレスポンスの遅れにつながります。

Visualforceページを作る

<apex:page controller="VisualforcePagePeriodicProcessingCtrl"
    sidebar="false"
    showHeader="false">
    <apex:form>
        <apex:actionPoller action="{!refresh}" interval="10" reRender="statusPanel" />
        <apex:outputPanel id="statusPanel">
            <div>Visualforceページの自動更新</div>
            <div>件数: <apex:outputText value="{!recordCount}" /></div>
            <div>ステータス: <apex:outputText value="{!statusLabel}" /></div>
        </apex:outputPanel>
    </apex:form>
</apex:page>

10秒ごとにrefreshを呼び出し、statusPanelだけを再描画します。件数とステータスは、それぞれコントローラのプロパティから表示します。

Apexクラスを作る

public with sharing class VisualforcePagePeriodicProcessingCtrl {
    public Integer recordCount { get; private set; }
    public String statusLabel { get; private set; }

    public VisualforcePagePeriodicProcessingCtrl() {
        statusLabel = '開始';
    }

    public void refresh() {
        List<Account> accs = [SELECT Id, Name FROM Account LIMIT 10];
        recordCount = accs.size();
        statusLabel = '取得件数 ' + recordCount + ' 件';
    }
}

actionPollerから呼ばれるたびにrefreshが実行され、getterで公開したプロパティの値が画面へ反映されます。DMLは行いません。

動作を確認する

  1. ページを開く

    「件数」と「ステータス」の表示が最初に1回出ます。

  2. 10秒待つ

    actionPollerがrefreshを呼び出し、statusPanelの中身だけが書き換わります。ページ全体の再読み込みは起きません。

  3. ブラウザの開発者ツールで通信を見る

    10秒間隔でVisualforceのAjaxリクエストが送られていることを確認します。

ビューステートとの付き合いかた

Visualforceのビューステートには170KBの上限があります。actionPollerは呼び出すたびにビューステートをサーバーとやり取りするため、reRenderの範囲を絞り、ページが保持するデータを必要な分だけにすることがポイントです。transientキーワードを付けた変数はビューステートに含まれないので、次の呼び出しまで持ち越さなくてよい値はtransientにします。

ここで間違えやすい

間違い何が起きるか
intervalを5秒未満にする指定できません。最小値は5秒です
actionPollerのactionでDMLや外部コールを行う呼び出すたびにその処理が走り、サーバー負荷とレスポンス遅延が起きます
@RemoteActionメソッドをactionに指定するactionPollerからは呼び出せません。通常のコントローラメソッドを使います
ページの保持データが多いままactionPollerで頻繁に更新するビューステートの上限(170KB)に近づきやすくなります

確認した環境

  • 2026年9月/Salesforce Summer '26(APIバージョン67.0)時点のVisualforce開発者ガイドで、actionPollerの属性とビューステートの上限を確認しています

まとめ

  • Visualforceページの自動更新には、標準コンポーネントのapex:actionPollerを使います
  • intervalの最小値は5秒、指定しないときの既定値は60秒です
  • actionPollerで呼ぶメソッドは軽量にします。DMLや外部コールは避けます
  • actionPollerのactionに指定できるのは通常のコントローラメソッドで、@RemoteActionは指定できません
  • ビューステートの上限は170KBです。reRenderの範囲と保持データを絞ることが、快適に動かすポイントです

参考:当時の画面

記事を最初に書いた当時の画面です。いまの手順と違うところは、各画像の説明に書いています。

Visualforceページの表示。件数10、ステータス開始と並んでいる
開いた直後の画面です。件数とステータスが一度だけ表示された状態を見てください。
Visualforceページの表示。件数10、ステータス処理中と並んでいる
処理の途中です。ページ全体は変わらず、ステータスの行だけが処理中に変わります。
Visualforceページの表示。件数10、ステータス正常終了と並んでいる
処理が終わった画面です。ステータスが正常終了に変わったところを見てください。
Visualforceページの表示。件数の行が消え、ステータスはページリロード待ち時間10秒
ページ全体を読み込み直す直前です。件数の行が消えている点が、重い更新であることを示しています。

Salesforceの導入・運用についてご相談ください

導入前の検討から、お使いの環境の改修・運用、AIとの連携まで承ります。状況を伺ったうえで、進め方をご提案します。