skysan's programming notebook

コーディングして思ったことなどを気ままに

Auraコンポーネント: 非同期処理の際はライフサイクルに気をつけようという話

はじめに

AuraコンポーネントからApexのアクションをコールする際に、Promiseを利用し汎用の非同期メソッドを実装しました。 then()を使ったメソッドチェーンで、レスポンス取得後の処理がうまく行きませんでした。

  1. 非公開属性のaura:attributeの値が変更されない
  2. e.force:closeQuickActionでモーダルが閉じない

該当コード

doAction: function(component, event, helper) {
  // Apexアクションのコール
  helper.callAction(component, 'c.getMessage', null)
  // resolve
  .then(function(result){
    // レスポンスの値をを非公開属性に設定
    component.set('v.result', result);

    // モーダルを閉じる(クイックアクション)
    $A.get('e.force:closeQuickAction').fire();
  })
  // reject
  .catch(function(error){
    console.error(error);
  })
}

原因

Promiseを利用した際、ライフサイクルからはずれてしまうため、コンポーネントへのアクセスに失敗するようです。

Promise はその resolve 関数と reject 関数を非同期に実行するため、コードは Lightning イベントループおよび通常の表示ライフサイクルの外側に存在します。

出典: *1

コールバックが $A.getCallback() でラップされないまま渡されると、コンポーネントの非公開属性にアクセスしようとしたときにアクセスチェックに失敗します。

出典: *2

対策

コールバックを $A.getCallback() でラップします。

出典: *3

以上。

$A.getCallback()でラップすることで、フレームワークのライフサイクルでキャッチできるようになります。

修正後のコード

doAction: function(component, event, helper) {
    // Apexアクションのコール
    helper.callAction(component, 'c.getMessage', null)
    .then(
        // resolve
        $A.getCallback(function(result) {

          // レスポンスの値をを非公開属性に設定
          component.set('v.result', result);

          // モーダルを閉じる(クイックアクション)
          $A.get('e.force:closeQuickAction').fire();
        }),

        // reject
        $A.getCallback(function(error) {
            console.error(error)
      })
    );
}

ソースコード全体はこちら

参考

所感

  • 公式ドキュメントはよく読もう(反省)