モデル変更時のコールバック処理 – Ember.js入門(24)

2014.06.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

渡辺です。

モデルの永続化関連のエントリーが続いていますが、もうそろそろ一段落です。 今回は、モデルの変更が成功/失敗した時のコールバック処理とモデルのロールバック/キャンセルについて解説します。

saveメソッドのコールバック処理

saveメソッドは非同期でHTTPリクエストを送信します。 そして、戻り値はPromise型です。 saveが成功/失敗した場合の処理は、次のようにthenメソッドで、コールバック関数として登録できます。

model.save().then(function() {
    // callback when Success
}, function() {
    // callback when Error
});

それでは典型的なパターンをみてみましょう。

モデルの更新画面において「更新」ボタンによりモデルの更新処理を行い、一覧画面などに遷移するパターンを想定します。

この時、モデルの保存処理はControllerのアクションとして定義することができます。 アクションとして定義することにより、ボタンなどのコントロールにバインド設定できるだけでなく、他の要素が変更時などなんらかの条件で発火(実行)することも可能です。

アクションでモデルのsaveメソッドを実行したとしても、保存処理は非同期で行われます。保存が完了した後、画面を遷移させるならば、成功時のコールバック処理でtransitionToRouteメソッドを利用します。

App.EditItemController = Ember.ObjectController.extend({
  actions: {
    doUpdate: function() {
      var self = this;
      model.save().then(function() {
        self.transitionToRoute('items');
      }, function() {
        // callback when Error
      });
    }
  }
});

transitionToRouteメソッドの第1引数にはルート名を指定します。

更新のキャンセル

更新画面で入力フォームとモデルの属性をバインディングしている場合、フォームの変更を行うことでモデルの属性も変更されます。この時、クライアントサイドのモデルは変更されているが、サーバサイドに反映されていないという状態となります。 したがって、そのまま画面を遷移させてしまうと、更新途中の状態でモデルが一覧画面などに表示されてしまいます。

更新画面から一覧画面などに戻るようなケースで更新内容をキャンセルするならば、モデルのrollbackメソッドを利用して、クライアントサイドでの変更を戻しましょう。

例えば、次のように「戻る」ボタンにアクションを設定し、rollbackしてから画面遷移を行います。

App.EditItemController = Ember.ObjectController.extend({
  actions: {
    doBack: function() {
      model.rollback();
      this.transitionToRoute('items');
    }
  }
});

モデルの状態遷移については、後日解説する予定です。

モデルの再読み込み

クライアントサイドでの変更はrollbackメソッドで戻すことができます。 サーバサイドでの変更を反映、すなわちRESTful APIを呼びなおし、モデルを最新状態にしたい場合は、reloadメソッドを利用します。

App.EditItemController = Ember.ObjectController.extend({
  actions: {
    doReload: function() {
      model.reload();
    }
  }
});

reloadメソッドはPromiseを戻り値としますので、成功時/失敗時のコールバック処理を記述することもできます。

まとめ

ember-dataでは、クライアントサイドならではの状態管理を自然に行うことができます。 ロールバックやリロードなどに関してもバインディングの仕組みと組み合わせることで、読み込まれた後の再描画処理で苦労することもありません。 ただし、それらの処理は常に非同期で行われており、非同期処理の結果はコールバック処理として定義しなければならないことは忘れないでください。