LWCから複数のApexを直列・並列で呼び出して比較する
Lightning Web Componentsで複数のApexメソッドを呼ぶとき、1つずつ待つ直列と、まとめて投げる並列では完了までの時間もエラーの起き方も変わります。実装とログで違いを確認します。
なぜ実行順を意識するのか
複数の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も同じ形です。
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との連携まで承ります。状況を伺ったうえで、進め方をご提案します。