LoginSignup
20
17

More than 5 years have passed since last update.

AngularJSの非同期処理をRxJSにつなげてみる

Posted at

AngularJSでは非同期処理のAPIとしてPromise API($q Service)が用意されています。

このPromise APIですがAngularJS v1.2でPromise/A+に準拠した形になりました。
Promise/A+の詳細については下記を参照してください。

AngularJSのPromise APIは非同期処理としては最小限の機能しか用意されておらず、複雑な非同期処理を書く場合は何かしらのライブラリが利用したくなります。

非同期処理のライブラリとしてはJSDeferredやjQuery.Deferredなどが有名ですが、今回はRxJSを使ってみます。

RxJSもv2.2でPromise/A+に準拠したObservable.fromPromiseが追加されたので、AngularJSのPromiseとRxJSを連携させて使うことが簡単にできるようになりました。

というわけで、AngularJSで用意されている$resource (Web APIを呼び出すためのサービス) を例にして、RxJSと連携させる方法を紹介したいと思います。
それぞれの基本的な使い方は省略するので、各種ドキュメントを参考にしてください。

単純な処理の比較

まずAngularJSのPromiseを使った場合と、RxJSを使った場合の単純な処理の書き方を比較してみます。

リクエストを投げて成功した場合と失敗した場合のコールバックをセットするには以下のように書きます。
これだと、Promiseを使ったほうが簡単ですね。

Promise
var res = $resource("/hoge");
res.get().$promise
  .then(
    function(data){ alert("success: " + data); }, 
    function(err){ alert("failure: " + err); }
  );
RxJS
var res = $resource("/hoge");
Rx.Observable.fromPromise(res.get().$promise)
  .subscribe(
    function(data){ alert("success: " + data); }, 
    function(err){ alert("failure: " + err); }
  );

1つ目のリクエストが完了したら、その結果を使って次のリクエストを呼び出す場合は以下のように。
これも、Promiseのほうがthenをつなげて書くだけなので分かりやすいですね・・・

Promise
var res1 = $resource("/hoge");
var res2 = $resource("/fuga/:id");
res1.get().$promise
  .then(function(data){
    return res2.get({id: data.id}).$promise;
  })
  .then(
    function(data){ alert("success: " + data); }, 
    function(err){ alert("failure: " + err); }
  );
RxJS
var res1 = $resource("/hoge");
var res2 = $resource("/fuga/:id");
Rx.Observable.fromPromise(res1.get().$promise)
  .selectMany(function(data){
    return Rx.Observable.fromPromise(res2.get({id: data.id}).$promise);
  })
  .subscribe(
    function(data){ alert("success: " + data); }, 
    function(err){ alert("failure: " + err); }
  );

RxJSの便利なメソッド

ここからは、Promiseだけで実装しようとすると複雑になるような処理を、RxJSで書いてみたいと思います。

まず、リクエストに成功するまで最大3回リトライする処理はこんな感じで書けます。

リトライ(RxJS)
var res = $resource("/hoge")
Rx.Observable.defer(function(){
    return Rx.Observable.fromPromise(res.get().$promise);
  })
  .retry(3)
  .subscribe(
    function(data){ alert("success: " + data); }, 
    function(err){ alert("failure: " + err); }
  );

複数のリクエストを投げて、その結果が揃うまで待ってから次の処理をするというのも簡単に書けます。

待ち合わせ(RxJS)
var res1 = $resource("/hoge");
var res2 = $resource("/fuga");
Rx.Observable.fromPromise(res1.get().$promise)
  .zip(Rx.Observable.fromPromise(res2.get().$promise), 
    function(data1, data2){ return [data1, data2]; }
  )
  .subscribe(
    function(data){ alert("success: " + data[0] + ":" + data[1]); }, 
    function(err){ alert("failure: " + err); }
  );

今回は簡単な例ばかりを示しましたが、RxJSには非常に便利なAPIがたくさん用意されているのでぜひ使ってみてください。

20
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
17