LWC

LWCから複数のApexを直列・並列で呼び出して比較する

Lightning Web Componentsで複数のApexメソッドを呼ぶとき、1つずつ待つ直列と、まとめて投げる並列では完了までの時間もエラーの起き方も変わります。実装とログで違いを確認します。

2025.07.17

なぜ実行順を意識するのか

複数のApexメソッドを呼ぶLWCでは、1つずつawaitする書き方と、まとめてPromise.allに渡す書き方があります。この2つは完了までの時間もエラーの起き方も違います。画面の応答を速くしたい場面ほど、どちらを選ぶかが効いてきます。

Apexコントローラ

両方の実装から呼び出す、共通のApexクラスです。

public with sharing class FromlwcToGetApexController {
    @AuraEnabled(cacheable=true)
    public static void getApexMethod1() {
        System.debug('getApexMethod1_start');
        for (Integer i = 0; i < 100; i++) {
        }
        System.debug('getApexMethod1_end');
    }
    @AuraEnabled(cacheable=true)
    public static void getApexMethod2() {
        System.debug('getApexMethod2_start');
        for (Integer i = 0; i < 100; i++) {
        }
        System.debug('getApexMethod2_end');
    }
    // getApexMethod3、getApexMethod4も同じ形(中身のSystem.debugの文字列だけが違う)
}

ループを回すだけの読み取り専用メソッドです。DMLは行いません。getApexMethod3・4も同じ形です。

4つとも戻り値はvoidです。@AuraEnabled(cacheable=true)は「クライアント側キャッシュを確認してから呼ぶ」ためのしくみなので、値を返さないメソッドに付けても、呼び出し側でキャッシュが効くことはありません。cacheable=trueが意味を持つのは、値を返す読み取り専用メソッドです。

直列で呼び出す実装

ボタンを押すごとに、4つのメソッドを1つずつawaitします。HTMLはボタン1つだけの画面です(label="直列実行")。

import { LightningElement } from 'lwc';
import getApexMethod1 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod1';
import getApexMethod2 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod2';
import getApexMethod3 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod3';
import getApexMethod4 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod4';

export default class FromlwcToGetApexSeries extends LightningElement {
    async handleExecution() {
        await getApexMethod1();
        await getApexMethod2();
        await getApexMethod3();
        await getApexMethod4();
    }
}

前のawaitが終わるまで、次のApex呼び出しは始まりません。

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>67.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__RecordPage</target>
    </targets>
</LightningComponentBundle>

apiVersionは67.0(Summer '26)へ上げています。

ボタンを押すと、開発者コンソールのログには次の順で出ます。1つ終わってから次が始まるので、_startと_endが交互に、メソッドの並び順どおりに出ます。

getApexMethod1_start
getApexMethod1_end
getApexMethod2_start
getApexMethod2_end
getApexMethod3_start
getApexMethod3_end
getApexMethod4_start
getApexMethod4_end

直列実行時のSystem.debugの出力順です。

並列で呼び出す実装

Promise.allに4つの呼び出しをまとめて渡すと、4つとも間を置かずに実行されます。HTMLはラベルが「並列実行」に変わるだけです。

import { LightningElement } from 'lwc';
import getApexMethod1 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod1';
import getApexMethod2 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod2';
import getApexMethod3 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod3';
import getApexMethod4 from '@salesforce/apex/FromlwcToGetApexController.getApexMethod4';

export default class FromlwcToGetApexParallel extends LightningElement {
    async handleExecution() {
        const values = await Promise.all([
            getApexMethod1(),
            getApexMethod2(),
            getApexMethod3(),
            getApexMethod4()
        ]);
    }
}

Promise.allに渡した4つは、間を置かずに実行されます。

js-meta.xmlは直列版と同じ内容です(apiVersionは67.0)。ボタンを押すと、ログの順は直列のときと変わります。

getApexMethod1_start
getApexMethod1_end
getApexMethod3_start
getApexMethod3_end
getApexMethod4_start
getApexMethod4_end
getApexMethod2_start
getApexMethod2_end

並列実行時のSystem.debugの出力順の一例です。

この順はメソッドの並び順どおりにはなりません。間を置かずに投げた複数の呼び出しが、サーバー側でどう処理されるかによって順が変わるためです。並列実行を選ぶときは、「書いた順に終わる」ことを前提にしないでください。

直列は完了までの時間が4つの合計に近づくかわりに実行順が保証され、並列は一番遅い1つに近づくかわりに順が保証されません。前の結果を次の呼び出しに使うなら直列を選びます。

ここで間違えやすい

間違い何が起きるか
前の結果を次のApex呼び出しの引数に使うのにPromise.allでまとめる前の結果がまだ無いので、想定した値を渡せません
Promise.allのどれか1つが例外を投げる他が成功していても全体がcatchに落ち、個別の結果は受け取れません
値を返さない・DMLを含むメソッドにcacheable=trueを付けるDMLを含む場合はデプロイまたは実行時にエラーになります。値を返さない場合はキャッシュの効果が無いだけで動作はします
js-meta.xmlのapiVersionを古いまま放置する新しいAPIバージョンで追加された構文や基本コンポーネントの挙動が使えません

個別の結果を保ちながら並列で呼びたい場合は、Promise.allではなくPromise.allSettledを使うと、失敗したものだけを見分けられます。

確認した環境

  • 2026年9月 / Salesforce Summer '26(APIバージョン67.0)時点の公式ガイドで、@wire・命令的呼び出し・@AuraEnabled(cacheable=true)の挙動を確認しています
  • ログの出力順は組織やタイミングによって変わることがあります

まとめ

  • LWCから複数のApexメソッドを呼ぶには、1つずつawaitする直列と、Promise.allでまとめる並列があります
  • 直列は実行順が保証され、並列は完了までの時間が短くなりますが順は保証されません
  • 前の結果を次の呼び出しに使うなら直列、独立した処理をまとめて速く終わらせたいなら並列を選びます
  • Promise.allは1つが失敗すると全体が失敗します。個別に結果を見たいときはPromise.allSettledを使います
  • @AuraEnabled(cacheable=true)は値を返す読み取り専用メソッドのためのものです。DMLを含むメソッドには付けられません
  • js-meta.xmlのapiVersionは67.0(Summer '26)へ上げています

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

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